Django - preset foreign key value in form field - django

I'm struggling to figure this out and hoping someone here can help me. I have a model, called "Team", which has a ForeignKey field that corresponds to the page I'm showing the ModelForm on ("Department"). Since it's on the page I want to set the ForeignKey in the backend (View or Form) rather than have the user select it.
Following others examples I set it up so the value would be added in the form portion, but when I submit the form I get the following error (followed by the request.POST print out) in the terminal:
<ul class="errorlist"><li>Department<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
<QueryDict: {'csrfmiddlewaretoken': ['KeEJF7KFr6l9dbkmZWA7u4Qg3eKqqFGcB2qq2AIEmilLP87AySi60ig3hJl6TBS0'], 'title': ['test'], 'description': [''], 'events': [''], 'current_status': [''], 'notes': [''], 'impact': [''], 'timeliness': [''], 'likelihood': [''], 'risk': [''], 'summary': [''], 'documents': ['']}>
FORM:
class TeamFormCreate(forms.ModelForm):
class Meta:
model = Team
fields = ('department', 'title', 'description', 'events', 'current_status', 'notes', 'impact',
'timeliness', 'likelihood', 'risk', 'summary', 'documents')
VIEW:
#login_required
def new_team(request):
if request.method == "POST":
form = TeamFormCreate(request.POST)
if form.is_valid():
team = form.save(commit=False)
team.author = request.user
team.modified_date = timezone.now()
team.save()
return redirect('/dashboard/1')
else:
return redirect('/dashboard/1')
else:
cd_id = request.GET.get('id', None)
form = TeamFormCreate(cd_id)
return render(request, 'app/sidebar_team.html', {'form': form})
MODEL:
class Team(models.Model):
department = models.ForeignKey('MyApp.Department', related_name='teams')
author = models.ForeignKey('auth.User')
modified_date = models.DateTimeField(default=timezone.now)
title = models.CharField(max_length=200)
description = models.TextField(blank=True, null=True)
events = models.TextField(blank=True, null=True)
current_status = models.TextField(blank=True, null=True)
notes = models.TextField(blank=True, null=True)
order = models.IntegerField(default=0)
# icon = models.ImageField()
# Document files
summary = models.FileField(upload_to='team', blank=True, null=True)
documents = models.FileField(upload_to='team', blank=True, null=True)
# Ratings
RATING_CHOICES = [(x, x) for x in range(1, 6)]
impact = models.IntegerField(choices=RATING_CHOICES, blank=True, null=True)
timeliness = models.IntegerField(choices=RATING_CHOICES, blank=True, null=True)
likelihood = models.IntegerField(choices=RATING_CHOICES, blank=True, null=True)
risk = models.IntegerField(choices=RATING_CHOICES, blank=True, null=True)
class Meta:
ordering = ['order']
def __str__(self):
return self.title

I was finally able to get this working by changing my View from a function based view to the following class based view.
# Required Imports
from django.views.generic import CreateView
from django.contrib.auth.mixins import LoginRequiredMixin
class TeamCreate(LoginRequiredMixin, CreateView):
model = Team
form_class = TeamFormCreate
template_name = 'app/sidebar_team.html'
def get_initial(self):
pk = self.request.GET.get('id')
return {
'department': pk,
}
def post(self, request, *args, **kwargs):
form = TeamFormUpdate(request.POST)
if form.is_valid():
team = form.save(commit=False)
team.author = request.user
team.modified_date = timezone.now()
team.save()
return redirect('/dashboard/' + str(team.department.id))
else:
return redirect('/dashboard/' + str(form.department.id))

Related

How to check validation on two fields in a form?

Need to add an image to the form either by entering a link to the image, or upload a file from your computer. If no options were entered when the form was submitted, or both options were entered, an error message should be displayed. And after successful loading, you should get to the image page.
models.py:
class Picture(models.Model):
url = models.URLField(blank=True, verbose_name='Ссылка на изображение')
image = models.ImageField(upload_to='pictures/%Y/%m/%d', width_field='image_width', height_field='image_height',
blank=True, verbose_name='Изображение')
image_width = models.IntegerField(default=0, blank=True, verbose_name='Ширина изображения')
image_height = models.IntegerField(default=0, blank=True, verbose_name='Высота изображения')
is_active = models.BooleanField(default=True, verbose_name='Актуальность изображения')
created = models.DateField(blank=True, null=True, default=timezone.now, verbose_name='Дата создания записи')
updated = models.DateField(blank=True, null=True, default=timezone.now, verbose_name='Дата ред-ия записи')
views.py:
def add_picture(request):
picture = Picture.objects.filter(is_active=True)
if request.method == 'POST':
form = PictureCreateForm(data=request.POST, files=request.FILES)
if form.is_valid():
form.save()
return render(request, 'add_picture.html', locals())
else:
messages.error(request, 'Ошибка, проверьте данные')
else:
form = PictureCreateForm()
return render(request, 'add_picture.html', locals())
forms.py: Here you need to define a method clean
class PictureCreateForm(forms.ModelForm):
class Meta:
model = Picture
fields = ('url', 'image')
def clean(self):
cd = self.cleaned_data
if cd['url'] and cd['image']:
raise forms.ValidationError('Ошибка!')
if not cd['url'] and not cd['image']:
raise forms.ValidationError('Ошибка!')
return cd
urls.py:
urlpatterns = [
path('', views.home, name='home'),
path('add_picture/', views.add_picture, name='add_picture'),
path('picture_detail/<int:id>/', views.picture_detail, name='picture_detail'),
]
You can make use of the clean(...) method of forms.ModelForm as
class PictureCreateForm(forms.ModelForm):
class Meta:
model = Picture
fields = ('url', 'image')
def clean(self):
cleaned_data = super().clean()
url = cleaned_data.get("url")
image = cleaned_data.get("url")
# do your logic here
# atlast
return cleaned_data

Required "owner_id" field is empty in the Database

I am trying to save the owner_id that is the same as the Logged In user/Authenticated user. But after I save the AddressBook form,the database saves the owner id with 'Null' value. Can someone help me knowing where am I going wrong.
models.py
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="profile")
mobiles = models.ManyToManyField(Product, blank=True)
class AddressBook(models.Model):
name = models.CharField(max_length=50)
owner = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True)
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
phone_number = models.CharField(validators=[phone_regex], max_length=17) # validators should be a list
line1 = models.CharField(max_length=100)
line2 = models.CharField(max_length=100, blank=True)
city = models.CharField(max_length=25)
state = models.CharField(max_length=25)
postcode = models.CharField(max_length=8)
country = models.CharField(max_length=25)
views.py
#login_required
def address(request):
existing_order = get_user_pending_order(request)
form = AddressBookForm()
context = {
'addressbook': AddressBook.objects.all(),
'form' : form,
'order' : existing_order,
}
return render(request, 'cart/user_address.html', context)
#login_required
def process_payment(request, order_id):
if request.method == 'POST':
form = AddressBookForm(request.POST)
if form.is_valid():
form.save()
return redirect (reverse('update-records', kwargs={'order_id': order_id}))
forms.py
from django import forms
from .models import AddressBook
class AddressBookForm(forms.ModelForm):
ADDRESS_TYPE = (
('Home', 'Home'),
('Work', 'Work'),
)
address_type = forms.ChoiceField(choices=ADDRESS_TYPE, widget=forms.RadioSelect)
class Meta:
model = AddressBook
fields = ['name', 'phone_number', 'line1', 'line2', 'city', 'state', 'postcode', 'country','address_type']
Database
You can save the form with commit=False, set the owner, and then save to the database:
if request.method == 'POST':
form = AddressBookForm(request.POST)
if form.is_valid():
address = form.save(commit=False)
address.owner = request.user.profile
address.save()

Django - Saving object worked one time but now it doesnt

i want to save an object to db and it worked one time but now it doesnt, i suspect that is something to do with the Glossary
Everything
views.py
#login_required
def product_form_view(request):
if request.method == 'POST':
form = Product_Form(request.POST, request.FILES)
if form.is_valid():
product_form = form.save()
product_form.save()
return redirect('product_management_view')
else:
form = Product_Form()
return render(request, 'product-form.html', {'form': form})
models.py
class Product (models.Model):
sub_chapter = models.ForeignKey(Sub_Chapter, on_delete=models.CASCADE)
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
glossary = models.ManyToManyField(Glossary, blank=True )
name = models.CharField(max_length=40, blank=False, null=False)
description = models.TextField(null=True)
product_image = models.ImageField(
upload_to='media/images/product_images', blank=False, null=False)
reference = models.CharField(max_length=40, blank=False, null=False)
width = models.PositiveIntegerField()
height = models.PositiveIntegerField()
length = models.PositiveIntegerField()
unit_price = models.DecimalField(
max_digits=15, decimal_places=4, null=True)
polution = models.DecimalField(decimal_places=8, max_digits=15, null=True, blank=True )
technical_implementation = models.TextField(null=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse_lazy("manufacter_product_view", kwargs={'id': self.pk})
forms.py
class Product_Form(forms.ModelForm):
sub_chapter = forms.ModelChoiceField(queryset=Sub_Chapter.objects.all(),
required=True, widget=forms.Select())
supplier = forms.ModelChoiceField(queryset=Supplier.objects.all(),
required=True, widget=forms.Select())
glossary = forms.ModelChoiceField(queryset=Glossary.objects.all(),
required=False, widget=forms.SelectMultiple())
product_image = forms.ImageField(
required=True, widget=forms.FileInput())
class Meta():
model = Product
fields =[ 'name', 'description', 'reference', 'width', 'height', 'length', 'polution', 'unit_price', 'technical_implementation', 'sub_chapter', 'supplier', 'glossary', 'product_image', ]
There is a bug in your product_form_view, you are calling the save method on product_form variable i.e product_form.save() but product_form will have None in it as form.save() will return None on successfully saving the object,so it will break the code there.And you don't need to again call the save method at all.Calling form.save() is enough for saving the object and you should move the code in else part out of it as it not currently handling the form invalid case.
Your code should be like this:
#login_required
def product_form_view(request):
if request.method == 'POST':
form = Product_Form(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('product_management_view')
form = Product_Form()
return render(request, 'product-form.html', {'form': form})

Avoid duplicates using django ModelForm

I have the following Model, ModelForm and View:
class Clinic(models.Model):
clinicid = models.AutoField(primary_key=True, unique=True)
name = models.CharField(max_length=60)
label = models.SlugField(max_length=25)
# logo =
email = models.EmailField(max_length=50, default='')
mobile = models.CharField(max_length=15, default='')
alternate = models.CharField(max_length=15, default='', blank=True)
about = models.CharField(max_length=250, blank=True)
state = models.CharField(max_length=25)
city = models.CharField(max_length=35)
locality = models.CharField(max_length=35)
pincode = models.IntegerField(default=0)
address = models.TextField(max_length=80, default='', blank=True)
website = models.URLField(blank=True)
class ClinicMetaForm(ModelForm):
class Meta:
model = Clinic
fields = [
'name',
'label',
'email',
'mobile',
'alternate',
'about',
'state',
'city',
'locality',
'pincode',
'address',
'website'
]
unique_together = ["name", "mobile", "email"]
def newclinic(request):
if request.method == 'POST':
print('New clinic setup')
form = ClinicMetaForm(request.POST)
form.save()
msg = "Successfully saved new clinic"
print(msg)
else:
form = ClinicMetaForm()
msg=''
return render(request, 'clinic/newclinic.html', {'form': form, 'msg': msg})
The problem is that when the same data is submitted, I get duplicate entries being saved, even though I am using unique_together. Why is this happening? How can I avoid it?
You should move unique_together to model.
And if you want to add some logic in your form just overwrite validate_unique
def validate_unique(self):
#your logic here
try:
self.instance.validate_unique(exclude=exclude)
except ValidationError, e:
self._update_errors(e.message_dict)

KeyError at /partners/create/ 'name'

I have a model Partner that is related to Product by a one to many relationships. I am using inlineformsets for the Product and I am gettig the following error which I don't understand:"KeyError at /partners/create/ 'name'"
my views are as follows:
def partner_create(request):
if not request.user.is_staff or not request.user.is_superuser:
raise Http404
ProductFormSet = inlineformset_factory(Partner, Product, form=ProductForm, extra=3, min_num=1)
if request.method == 'POST':
partnerForm = PartnerForm(request.POST or None, request.FILES or None)
formset = ProductFormSet(request.POST, request.FILES, queryset=Product.objects.none())
if partnerForm.is_valid() and formset.is_valid():
instance = partnerForm.save(commit=False)
instance.save()
for form in formset.cleaned_data:
name = form["name"]
description = form["description"]
price = form["price"]
image = form["image"]
product = Product(partner=instance, name=name, description=description, price=price, product_image=image)
product.save()
messages.success(request, "Partner Successfully Created")
else:
print partnerForm.errors, formset.errors
else:
partnerForm = PartnerForm()
formset = ProductFormSet(queryset=Product.objects.none())
return render(request, "partner_form.html", {"partnerForm": partnerForm, "formset": formset})
my forms.py are as follows:
class PartnerForm(forms.ModelForm):
mission = forms.CharField(widget=PagedownWidget(show_preview=False))
vision = forms.CharField(widget=PagedownWidget(show_preview=False))
# publish = forms.DateField(widget=forms.SelectDateWidget)
class Meta:
model = Partner
fields = [
"name",
"logo",
"banner_image",
"mission",
"vision",
"website_link",
"fb_link",
"twitter_link",
"ig_link",
]
class ProductForm(forms.ModelForm):
image = forms.ImageField(label='Image')
class Meta:
model = Product
fields = [
"partner",
"name",
"description",
"price",
"image",
]
My models.py are as follows:
def upload_location(instance, filename):
#filebase, extension = filename.split(".")
# return "%s/%s" %(instance.name, instance.id)
PartnerModel = instance.__class__
exists = PartnerModel.objects.exists()
if exists:
new_id = PartnerModel.objects.order_by("id").last().id + 1
else:
new_id = 1
file_name, file_extension = filename.split('.')
return "%s/%s/%s-%s.%s" %('partner',instance.name, file_name, new_id, file_extension)
class Partner(models.Model):
name = models.CharField(max_length=120)
logo = models.ImageField(upload_to=upload_location,
null=True,
blank=True,
width_field="width_field",
height_field="height_field")
banner_image = models.ImageField(upload_to=upload_location,
null=True,
blank=True,
width_field="width_field",
height_field="height_field")
mission = models.TextField()
vision = models.TextField()
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
# text = models.TextField()
website_link = models.CharField(max_length=120)
fb_link = models.CharField(max_length=120)
twitter_link = models.CharField(max_length=120)
ig_link = models.CharField(max_length=120)
slug = models.SlugField(unique=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
def __unicode__(self):
return self.name
def get_absolute_url(self):
return reverse("partners:detail", kwargs={"slug": self.slug})
# return "/partner/%s/" %(self.id)
def get_markdown(self):
mission = self.mission
markdown_text = markdown(mission)
return mark_safe(markdown_text)
#Creating a many to one relationship so that one can upload many Products
class Product(models.Model):
partner = models.ForeignKey(Partner, default=None)
name = models.CharField(max_length=120)
product_image = models.ImageField(upload_to=upload_location,
# product_image = models.ImageField(upload_to= (upload_location + '/' + name), Something like this need to append actual product name so these dont just get dumped in the media for partners
null=True,
blank=True,
width_field="width_field",
height_field="height_field",
verbose_name='Image',)
description = models.TextField()
price = models.DecimalField(max_digits=6, decimal_places=2, null=True)
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
def __unicode__(self): # __unicode__ on Python 2
return self.name
I would really like to understand what is going on as well as how to fix it or a hint in the right direction. Thank you in advance for your help!
To find out why you're getting the error, you should add some printing or logging to your code. What is the value of formset.cleaned_data? Is it what you think it should be?
There's a simpler approach that looping through the formset's cleaned_data. The docs show how to save a formset. You can save with commit=False, then set the partner field before saving to the database.
products = formset.save(commit=False)
for product in products:
product.partner=instance
product.save()
Note that if you do this, you should probably switch to a modelformset_factory instead of inlineformset_factory, and remove partner from the list of the fields of the ProductForm.
The formset form save method seems incorrect, use something like
for form in formset.cleaned_data:
if form.is_valid():
name = form.cleaned_data.get("name")
description = form.cleaned_data.get("description")
price = form.cleaned_data.get("price")
image = form.cleaned_data.get("image")
Please lemme know if this works :)