0

I have to send some data to my database where I have a phone object. For this I need to select the desired phone number and insert the desired information to the database. A requirement is to display the phone numbers that belongs to the current login user.
I use Django model named Phone and a modelForm named phoneForm.

class Phone(models.Model):
    user = models.ForeignKey(User)
    phone_num = models.ForeignKey(Sim, null=True)
    imei = models.CharField(max_length=30, primary_key=True)
    num_calls = models.CharField(max_length=20, null=True, blank=True)
    time_btwn_calls = models.CharField(max_length=20, null=True, blank=True)
    psap = models.CharField(max_length=30, null=True, blank=True)

class Sim(models.Model):
    phone_num = models.CharField(max_length=30, primary_key=True)
    pin = models.CharField(max_length=15)
    puk = models.CharField(max_length=15)

class phoneForm(ModelForm):

    class Meta:
        model = Phone
        fields = ['phone_num', 'num_calls', 'time_btwn_calls', 'psap']
        widgets = {'phone_num': Select(attrs={'class': 'form-control'}), 
                'num_calls': TextInput(attrs={'class': 'form-control'}),
                'time_btwn_calls': TextInput(attrs={'class': 'form-control'}), 
                'psap': TextInput(attrs={'class': 'form-control'})
                  }
        labels = {
                'phone_num': ('Select phone number'),
                'num_calls': ('Number of calls'),
                'time_btwn_calls': ('Time between calls'),
                'psap': ('PSAP'),
        }

        def __init__(self, *args, **kwargs):
            super(phoneForm, self).__init__(*args, **kwargs)
            self.queryset = Phone.objects.filter(user_id = request.user.id).values('phone_num')

How can I acces the database properly to filter the phone_num values that belongs to the current user and then set them in phone_num choices?

My template is:

<div class="row">
    <div class="col-md-6 col-sm-offset-3">
        <form method="post" action="" enctype="multipart/form-data">
            {% csrf_token %}  <!-- obligatorio para protegerse de ataques maliciosos -->
            {{ form.as_p }} <!-- pasamos la variable form y con as_p conseguimos <p> -->
            <button type="submit" class="btn btn-primary">Send to TCU</button>
        </form>
    </div>

And my view.py:

def phone_config(request):
    phone = Phone.objects.get(phone_num=611111111)

    if request.method == 'POST':
        form = phoneForm(request, request.POST, instance=phone)
        if form.is_valid():
            form.save()
            return redirect(reverse('gracias'))
    else:
        form = phoneForm(request, instance=tcu)
    return render(request, 'heroconfigurer/heroconfigurer.html', {'form': form})


def gracias_view(request):
    return render(request, 'heroconfigurer/gracias.html')
Alasdair
  • 298,606
  • 55
  • 578
  • 516
picador
  • 157
  • 4
  • 19
  • I post it now, thank you for your help – picador Dec 18 '15 at 11:35
  • Is there a particular reason why you are using a `CharField` as a foreign key? Normally I would recommend letting Django create the primary key automatically. – Alasdair Dec 18 '15 at 11:54

1 Answers1

3

To modify the phone_num field in your form, you access self.fields['phone_num'] in your form's __init__ method.

class phoneForm(ModelForm):

    class Meta:
        model = Phone
        ...

    def __init__(self, user, *args, **kwargs):
        super(phoneForm, self).__init__(*args, **kwargs)
        phone_nums = Phone.objects.filter(user=user).values_list('phone_num', flat=True)
        self.fields['phone_num'].queryset = Sim.objects.filter(phone_num__in=phone_nums)

When you initialise the form in your view, you need to pass the user, e.g.

form = phoneForm(user, request.POST)

If that doesn't work, please explain why and show your Sim model.

Note a couple of other changes:

  • No need to use values()
  • If Sim.user is a foreign key, then you can simplify the filter to filter(user=request.user)
  • The user has been added to the form's __init__ method.
Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • This *won't* work, as there is no reference to `request` in that method. You'll need to pass it in via kwargs. – Daniel Roseman Dec 18 '15 at 10:13
  • and what about setting the filtered values to the phone_num choices, It still displays all the phone_numbers store in the database – picador Dec 18 '15 at 10:21
  • I wasn't entirely sure what you want, because you haven't shown the `Sim` model. Does the `Sim` model have a `phone_num` field that you want to display? – Alasdair Dec 18 '15 at 10:25
  • I personally prefer the keyword approach since it would allow the form to display all phone numbers as well at some point if so desired (also would only pass in a ref to the user) – Sayse Dec 18 '15 at 10:25
  • @Alasdair the ansewr is yes. When I add form = phoneForm(request) I get an error: 'WSGIRequest' object has no attribute 'get'. I update my question with the template – picador Dec 18 '15 at 10:27
  • @Sayse, I agree, passing `user` is better so I changed it. I'm not sure what you mean by the 'keyword approach'. – Alasdair Dec 18 '15 at 10:35
  • @ferran, I can't understand that error without seeing the full traceback (note I've updated my answer, so try that first) – Alasdair Dec 18 '15 at 10:35
  • 2
    @Alasdair - Oh sorry, you can see an example in [this answer](http://stackoverflow.com/a/1204136/1324033) (just a random answer I found that uses it). essentially you use the `kwargs` to pass the data rather than specify an additional parameter – Sayse Dec 18 '15 at 10:37
  • 1
    What do you need help with? Have you tried the latest version of my answer. If it gives an error, what is the full traceback? – Alasdair Dec 18 '15 at 11:03
  • The first answer is working, displaying the imei(pk instead of phone_num) – picador Dec 18 '15 at 11:34
  • I don't understand what's going on. The primary key of the `Sim` model is `phone_num`, it doesn't have an `imei` field, so I don't understand why it would show the `imei` instead of the phone number. – Alasdair Dec 18 '15 at 11:39
  • self.fields['phone_num'].queryset = Phone.objects.filter(user_id = request.user.id) I have the user relation in the Phone model... – picador Dec 18 '15 at 11:44
  • `Phone.phone_num` is a foreign key to `Sim`, so you **must** use a `Sim` queryset, not a `Phone` queryset. If you want to filter on the `Phone.user` field, try `Sim.objects.filter(phone__user=user)`. – Alasdair Dec 18 '15 at 11:53
  • I've removed the `ModelChoiceField` from my answer. I don't think you need it in this case, because you have `Sim.phone_num` as the primary key. – Alasdair Dec 18 '15 at 11:56
  • yes you are rigth, but still an error: Unsupported lookup 'user' for CharField or join on the field not permitted – picador Dec 18 '15 at 12:04
  • I think that might be because you have a CharField as the primary key (I would normally recommend against this). You can probably work around it by doing something like `phone_nums = Phone.objects.filter(user=user).values_list('phone_num', flat=True)`, then using `Sim.objects.filter(phone_num__in=phone_nums)` as the queryset. – Alasdair Dec 18 '15 at 12:30
  • I update my full code and I would be gratefull if you could answer a last question. In my views.py I use an instance of the phone_num=611111111 so all the data displayed in the form will submit on that phone_num. How can I change that for insert the data in the desired/selected phone_num ? – picador Dec 18 '15 at 13:14
  • This answer already has many comments and is difficult to follow. I've rolled back your question to the previous version, so that it matches the answer. I think it would be better if you asked a new question about changing your views to allow editing different numbers. – Alasdair Dec 18 '15 at 13:25
  • ok I posted the new question: http://stackoverflow.com/questions/34391299/send-selected-value-from-django-forms-to-views-py – picador Dec 21 '15 at 09:21
  • @Alasdair could you ckeck it please ? – picador Dec 21 '15 at 10:12