I am struggling with how I should structure my application and some things are not working as expected.
What I am working on is a form that is supposed to let a user set a billing (possibly also a shipping) address. Unfortunately, if I include the option billing address in the profile form, it lets the user choose from all addresses in the database, also from other users.
If I omit this, the address that the user enters gets saved in the database, but it is not connected to the user, and every time the user updates the form it saves the address again.
What I want is:
- Address gets saved in relation to the user
- Addresses are not redundant
- Users shouldn’t be able to see the address of another user
I will attach the snippets that I think are relevant below. I am not sure if and how to change the views function in order to save the input from the billing address in relation to my user or if I should change the models, which I would rather avoid because I want to keep them simple.
forms.py
...
class ProfileEditForm(forms.ModelForm):
date_of_birth = forms.DateInput()
class Meta:
model = Profile
fields = ('date_of_birth', 'biography', 'description')
class AddressUSEditForm(forms.ModelForm):
class Meta:
model = AddressUS
fields = ('name', 'address_one', 'address_two', 'city', 'state', 'zipcode')
models.py
... # includes import of AddressUS Model
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
date_of_birth = models.DateField(blank=True, null=True)
address_billing = models.OneToOneField(AddressUS, null=True, blank=True,
on_delete=models.CASCADE, related_name='billing')
# address_shipping = models.OneToOneField(AddressUS, null=True, blank=True,
# on_delete=models.CASCADE, related_name='shipping')
biography = models.CharField(max_length=300, null=True, blank=True)
description = models.CharField(max_length=2000, null=True, blank=True)
def __str__(self):
return f'{self.user.username} Profile'
def save(self, *args, **kwargs):
super().save()
someroute/models.py
...
class AddressUS(models.Model):
name = models.CharField(max_length=400, null=True, blank=True)
address_one = models.CharField(max_length=300)
address_two = models.CharField(max_length=300)
city = models.CharField(max_length=200)
state = models.CharField(max_length=2)
zipcode = models.IntegerField()
def __str__(self):
return self.address_one + ' ' + self.address_two + ' ' + self.city + ', ' + self.state
def save(self, *args, **kwargs):
super().save()
views.py
...
@login_required
def edit(request):
if request.method == 'POST':
user_form = UserEditForm(instance=request.user,
data=request.POST)
profile_form = ProfileEditForm(instance=request.user.profile,
data=request.POST,
files=request.FILES)
address_form_billing = AddressUSEditForm(instance=request.user.profile.address_billing,
data=request.POST)
if user_form.is_valid() and profile_form.is_valid() and address_form_billing.is_valid():
user_form.save()
profile_form.save()
address_form_billing.save()
messages.success(request, 'Profile updated successfully')
else:
messages.error(request, 'Error updating your profile')
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
address_form_billing = AddressUSEditForm(instance=request.user.profile.address_billing)
return render(request,
'users/edit.html',
{'user_form': user_form,
'profile_form': profile_form,
'address_form_billing': address_form_billing})
Any kind of help would be highly appreciated, I really need to get some order into this mess. If you need some more information to be able to answer the question I will gladly provide it.
Thanks!!!