1

So, I want to log the searches which people make (oh noes, I'm the NSA, and all). To that end, I have this Search model:

class Search(models.Model):
    search_string = models.CharField(max_length=40)
    ip_record = models.GenericIPAddressField()
    date_searched = models.DateTimeField(default=datetime.now())

Then, I have this form:

class SearchForm(ModelForm):
    class Meta:
        model = Search
        fields = '__all__'

How do I make it that there is only the search_string displayed? I have tried setting editable=False and using only the search_string field as a singleton list provided to fields, but that doesn't populate the other fields and creates an integrity error:

IntegrityError at /endos/
NOT NULL constraint failed: backend_search.ip_record

How should I be creating this form? And how do I create it with only one field and with the other fields being populated by computer?

j-i-l
  • 10,281
  • 3
  • 53
  • 70
ifly6
  • 5,003
  • 2
  • 24
  • 47

1 Answers1

2

In your SearchForm Meta, write:

fields = ('search_string', ) # mind the ,

If you only want to put the search_string into the form.

But you are not quite done! The problem is - as the IntegrityError indicates - that you do not set the ip_records, which needs to be set in order for the new Search object to be written to the database. To set the field you can save the form without committing, set the ip_records, then commit. This all in the view:

if form.is_valid():
    obj = form.save(commit=False)
    obj.ip_record = get_IP(request)  # get_IP is to define (see below)
    obj.save()

For getting the IP, this might help:

def get_IP(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

The function is from this SO question.

j-i-l
  • 10,281
  • 3
  • 53
  • 70