i have one model userprofile which is connected to User by onetoone relationship. i am trying to create combined form for both user and userprofile form but it is showing onetoonedescripter has no attribute _meta.
views.py
'''
def UpdateProfile(request):
if request.method =='POST':
EUF_form = EditUserForm(request.POST, instance=request.user )
EPF_form = EditProfileForm(request.POST, instance=request.user.Profile )
if EUF_form.is_valid() and EPF_form.i_valid():
EUF_form.save()
EPF_form.save()
return HttpResponse("Profile updated succesfully.")
return render(request, 'profile_page.html')
else:
EUF_form = EditUserForm(instance=request.user)
EPF_form = EditProfileForm(instance=request.user.profile)
return render(request, 'edit_profile.html', {'EUF_form':EUF_form, 'EPF_form':EPF_form})
'''
models.py
'''
class Profile(models.Model):
user = models.OneToOneField(User, on_delete= models.CASCADE)
mobile = models.CharField(max_length=20, blank=True)
bio = models.CharField(max_length=300, default='')
avatar = models.ImageField(upload_to='avatars', blank=True)
birthday = models.DateField(blank=True, default='1990-12-01')
website = models.CharField(blank=True, max_length=256)
gender = models.CharField(blank=True, max_length=20, choices=[('M','Male'), ('F','Female'),('O','Other')])
def __str__(self):
return self.user.username
'''
forms.py
'''
class EditUserForm(ModelForm):
first_name = forms.CharField(widget=forms.TextInput(
attrs={'class': 'form-control','type':'text','name': 'first_name'}),
label="First Name")
last_name = forms.CharField(widget=forms.TextInput(
attrs={'class': 'form-control','type':'text','name': 'last_name'}),
label="Last Name")
username = forms.CharField(widget=forms.TextInput(
attrs={'class': 'form-control','type':'text','name': 'username'}),
label="Username")
email = forms.EmailField(widget=forms.TextInput(
attrs={'class': 'form-control','type':'text','name': 'email'}),
label="Email")
class Meta:
model = User
fields = ['first_name','last_name','username','email']
class EditProfileForm(ModelForm):
mobile = forms.CharField(widget=forms.TextInput(
attrs={'class': 'form-control','type':'tel','name': 'mobile'}),
label="Phone number")
bio = forms.CharField(widget=forms.Textarea,
label="Bio")
birthday = forms.DateField(widget=forms.DateInput(
attrs={'class': 'form-control','type':'date','name': 'birthday'}),
label="Username")
website = forms.URLField(widget=forms.URLInput(
attrs={'class': 'form-control','type':'url','name': 'website'}),
label="website")
gender = forms.ChoiceField(choices=[('M','Male'), ('F','Female'),('O','Other')],
widget=forms.Select ,
label="gender")
class Meta:
model = Profile
fields = ['mobile','bio','birthday','website','gender']
'''
Related
I'm making something like this: admin creates form manually, and user is automatically created with this form.
But I need to add association that form to a new automatically created user, that's where I'm stuck. How can I make user auto registration to associate that form
I need this because I want to then to show 'filtered, created' form by user.
Views.py
def create_driver_view(request):
if request.method == "POST":
add_driver = DriverForm(request.POST)
add_driver_files = request.FILES.getlist("file")
if add_driver.is_valid():
email = request.POST['email']
usern = 'test'
passw = 'test'
user = User.objects.create_user(email = email, username = usern, password = passw)
user.save()
f = add_driver.save(commit=False)
f.user = request.user
f.save()
for i in add_driver_files:
DriversFiles.objects.create(driver_files=f, file=i)
return redirect('drivers:list_driver')
else:
print(add_driver.errors)
else:
add_driver = DriverForm()
add_driver_files = DriverFormUpload()
return render(request, "drivers/add.html", {"add_driver": add_driver, "add_driver_files": add_driver_files})
Forms.py
class DriverForm(forms.ModelForm):
class Meta:
model = Drivers
fields = [
'full_name',
'phone_number',
'email',
'address',
'country',
'state',
'city',
'zip',
'birth_date',
'license_no',
'license_exp_date',
'last_medical',
'next_medical',
'last_drug_test',
'next_drug_test',
'status',
]
class DriverFormUpload(forms.ModelForm):
class Meta:
model = DriversFiles
fields = [
'file',
]
widget = {
'file': forms.ClearableFileInput(attrs={'multiple': True}),
}
Models.py
STATUS = ((0, 'Inactive'), (1, 'Active'))
class Drivers(models.Model):
full_name = models.CharField(max_length=50, default=None)
phone_number = models.CharField(max_length=50, default=None)
email = models.EmailField(unique=True,max_length=255, default=None)
address = models.CharField(max_length=70, default=None)
country = models.CharField(max_length=50, default=None)
state = models.CharField(max_length=50, default=None)
city = models.CharField(max_length=50, default=None)
zip = models.CharField(max_length=50, default=None)
birth_date = models.DateField(default=None)
license_no = models.IntegerField(default=None)
license_exp_date = models.DateField(default=None)
last_medical = models.DateField(default='', blank=True, null=True)
next_medical = models.DateField(default='', blank=True, null=True)
last_drug_test = models.DateField(default='', blank=True, null=True)
next_drug_test = models.DateField(default='', blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=1)
class DriversFiles(models.Model):
file = models.FileField(upload_to="media/", blank=True, null=True)
driver_files = models.ForeignKey('Drivers', on_delete=models.CASCADE, default=None, null=True)
I am trying to save information from the form created out of the Django model. I am really not much experienced as this is my second project.
Here is my view
def profile_create_view(request):
form = ProfileCreateForm(request.POST or None)
if form.is_valid():
form.save
form = ProfileCreateForm()
context = {
'form':form
}
return render(request, 'users/profile', context)
my form is here
class ProfileCreateForm(forms.ModelForm):
class Meta:
model = Profile
fields = [
'avatar',
'user_type',
'first_name',
'last_name',
'gender',
'email',
'phonenumber',
'birth_date',]
and then my model is here
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(upload_to = '', default = path_and_rename, blank=True)
provider = 'provider'
requester = 'requester'
user_types = [
(provider, 'provider'),
(requester, 'requester'),
]
user_type = models.CharField(max_length=155, choices=user_types, default=requester)
first_name = models.CharField(max_length=255, default='')
last_name = models.CharField(max_length=255, default='')
GENDER_MALE = 'Male'
GENDER_FEMALE = 'Female'
OTHER = 'Other'
GENDER_CHOICES = [
(GENDER_MALE, 'Male'),
(GENDER_FEMALE, 'Female'),
(OTHER, 'Other'),
]
gender = models.CharField(max_length=15, choices=GENDER_CHOICES, blank=True)
email = models.EmailField(default='none#email.com')
phonenumber = models.CharField(max_length=15, default='')
birth_date = models.DateField(default='1975-12-12')
Strange things happen in the view function, you have to rebuild it like this.
def profile_create_view(request):
if request.method == "POST":
form = ProfileCreateForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('/')
else:
form = form(instance=request.user)
return render(request, 'manage_authors.html', {'form': form})
sorry, I had forgotten I solved it by changing the model on avatar from
'avatar = models.ImageField(upload_to = '', default = path_and_rename, blank=True)'
to
avatar = models.ImageField(upload_to = 'uploads/', default='uploads/default.jpg')
I have a form that users can fill to leave a review. On the same page, the reviews are displayed with a button to edit the review. When the edit button is clicked, I would like for the form to be pre-filled with the appropriate review data, so that it can be edited and updated in the database.
models
class Clinic(models.Model):
practitioner = models.OneToOneField(User, on_delete=models.CASCADE)
lat = models.FloatField(null=True, blank=True)
lng = models.FloatField(null=True, blank=True)
web = models.CharField(null=True, blank=True, max_length=128)
name = models.CharField(max_length=128, )
phone = PhoneNumberField()
description = models.TextField(max_length=5000)
street = models.CharField(max_length=128, )
city = models.CharField(max_length=128, )
def __str__(self):
return self.name
def save(self):
super().save()
class Reviews(models.Model):
title = models.CharField(max_length=128)
body = models.TextField(max_length=500)
author = models.ForeignKey(User, on_delete=models.CASCADE)
clinic = models.ForeignKey(Clinic,
null=True,
blank=True,
on_delete=models.CASCADE)
Form
class ReviewForm(forms.ModelForm):
class Meta:
model = Reviews
fields = (
'title',
'body',
)
View
def clinic_profile(request, clinic_id):
clinic = Clinic.objects.filter(pk=clinic_id)
form = ReviewForm(request.POST)
if request.method == 'POST':
if form.is_valid():
r_clinic = Clinic.objects.get(pk=clinic_id)
title = form.cleaned_data.get("title")
body = form.cleaned_data.get("body")
review = Reviews(title=title,
body=body,
author=request.user,
clinic=r_clinic)
review.save()
messages.success(request, f'Thank you for leaving a review!')
clinic_reviews = Reviews.objects.filter(clinic=clinic_id)
latlng = {
"lat": clinic[0].lat,
"lng": clinic[0].lng,
"name": clinic[0].name
}
def get_mods():
profile = Profile.objects.filter(user=Clinic.objects.get(
pk=clinic_id).practitioner)
mods = profile[0].mods.all().values('name') if profile else []
mods = [(q['name']) for q in mods]
return mods
return render(
request, 'clinic_profile.html', {
'clinic': clinic,
'mods': get_mods,
'latlng': latlng,
'api_key': api_key,
'reviews': clinic_reviews,
'form': form,
})
Screenshot
Inline formset is valid when all the fields are empty but when i fill any one field and submit the formset becomes invalid ?
forms.py
class ContactPersonForm(forms.ModelForm):
phone_number = PhoneNumberField(error_messages={'required': 'Please enter your phone number'}, widget=forms.TextInput(attrs={'placeholder': _('Mobile Number')}))
mobile_number = PhoneNumberField(error_messages={'required': 'Please enter your phone number'}, widget=forms.TextInput(attrs={'placeholder': _('Mobile Number')}))
class Meta:
model = ContactPerson
exclude = ('client',)
widgets = {
'first_name': forms.TextInput(attrs={'placeholder': _('First Name')}),
'last_name': forms.TextInput(attrs={'placeholder': _('Last Name')}),
'email': forms.EmailInput(attrs={'placeholder': _('Email')}),
'phone_number': forms.TextInput(attrs={'placeholder': _('Phone Number')}),
'mobile_number': forms.TextInput(attrs={'placeholder': _('Mobile Number')}),
'skype_name': forms.TextInput(attrs={'placeholder': _('Skype Name / Number')}),
'designation': forms.TextInput(attrs={'placeholder': _('Designation')}),
'department': forms.TextInput(attrs={'placeholder': _('Department')}),
}
ContactPersonFormSet = inlineformset_factory(Client, ContactPerson, form=ContactPersonForm, extra=1)
models.py
class ContactPerson(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE)
salutation = models.CharField(max_length=4, choices=SALUTATIONS)
first_name = models.CharField(max_length=128)
last_name = models.CharField(max_length=128)
email = models.EmailField()
phone_number = models.CharField(max_length=20)
mobile_number = models.CharField(max_length=20)
skype_name = models.CharField(_('Skype Name / Number'), max_length=128)
designation = models.CharField(max_length=128)
department = models.CharField(max_length=128, null=True)
You may add a custom FormSet by inheriting BaseInlineFormSet and make use of the property has_changed()
class ContactPersonFormSet(forms.BaseInlineFormSet):
def clean(self):
if self.has_changed() == False:
raise forms.ValidationError('Please add at least one contact person.')
and then specify it in your fomset_facotry, like
ContactPersonFormSet = inlineformset_factory(Client, ContactPerson, form=ContactPersonForm, formset=ContactPersonFormSet, extra=1)
In models.py:
class Client(AbstractBaseUser):
username = models.CharField(max_length=32, unique=True)
email = models.EmailField('email address', unique=True, db_index=True)
avatar = models.ImageField('avatar', upload_to='avatars')
id = id(object)
class Order(models.Model):
class Meta():
db_table = 'order'
short_desc = models.CharField(max_length=30)
subject = models.ForeignKey(Subject, blank=True)
user_id = models.ForeignKey('Client', to_field='id', related_name='client_id', default='0', blank=True)
performer_id = models.ForeignKey('Client', to_field='id', related_name='performer_id', default='0', blank=True)
worktype = models.ForeignKey(Type, blank=True)
level = models.IntegerField(default=0, blank=True)
readiness = models.BooleanField(default=False, blank=True)
description = models.TextField(max_length=2000, blank=True)
file = models.FileField(upload_to='orderfiles', blank=True)
#maxdate = models.DateField(blank=True)
addate = models.DateField(auto_now=True, blank=True)
price = models.IntegerField(max_length=10, blank=True)
responses = models.IntegerField(blank=True)
In forms.py:
class AddOrderForm(forms.ModelForm):
short_desc = forms.CharField(widget=forms.TextInput,label="Краткое описание(послужит именем)")
subject = forms.ModelChoiceField(queryset=Subject.objects.all(), label="Предмет")
worktype = forms.ModelChoiceField(queryset=Type.objects.all(), label="Тип")
level = forms.IntegerField(widget=forms.TextInput,label="Уровень сложности (от 1 до 5)")
description = forms.CharField(widget=forms.TextInput,label="Полное описание")
#maxdate = forms.DateField(widget=forms.TextInput,label="maxdate")
price = forms.IntegerField(widget=forms.TextInput,label="Ваша цена")
responses = forms.IntegerField(widget=forms.TextInput,label="Кол-во ответов на заказ")
class Meta:
model = Order
fields = ['short_desc', 'level', 'description', 'price', 'responses', 'subject', 'worktype']
In views.py:
def addorder(request, user_id):
"""
Adding Order view
"""
if request.POST:
form = AddOrderForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
return redirect('/')
auth1 = auth.get_user(request).username
return render_to_response('customer.html', { 'form': form,'username' : auth1}, context_instance=RequestContext(request))
I need the field user_id in class Order to be initialized immediately after adding order(). Where should I do it and in which way? I need something like this logic: Client adds an Order through AddOrderForm and then user_id field of just added object of class Order has to be initialized with an object of class Client, whose id equals user_id in parameters of addorder() function.
You can do that using commit=False while saving the form. This is typical way of saving the object using model form which has fewer fields.
def addorder(request, user_id):
"""
Adding Order view
"""
if request.POST:
form = AddOrderForm(request.POST)
if form.is_valid():
order = form.save(commit=false)
order.client_id = Client.objects.get(id=user_id)
order.save()
return redirect('/')
else:
return redirect('/')
auth1 = auth.get_user(request).username
return render_to_response('customer.html',
{ 'form': form,'username' : auth1},
context_instance=RequestContext(request))
Disclaimer: Handle errors e.g. Client.objects.get() may fail. Use appropriate fields to search.