excluding id field in an inline formset when saving - python

I have two models, connected by a foreign key. One is an inline formset. For some reason, the formset ids are being identified as Primary Keys in the database, and every time the form is submitted, the table belonging to the formset is basically overwritten. When saving, how do I ignore the formset ids
models.py
class Student(models.Model):
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=40)
email = models.EmailField()
class Courses(models.Model):
student = models.ForeignKey(Student)
course_name = models.CharField(max_length=40)
start_time = models.TimeField()
forms.py
class CoursesForm(forms.ModelForm):
class Meta:
model = Courses
exclude = ("student",)
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = "__all__"
views.py
...
def post(self, request, *args, **kwargs):
sform = StudentForm(request.POST, instance=Student())
CourseSchedule = inlineformset_factory(Student, Courses, form=CoursesForm, can_delete=False, extra=0, min_num=1)
cforms = CourseSchedule(data=request.POST)
if sform.is_valid() and cforms.is_valid():
sform_obj = sform.save()
for cform in cforms.forms:
cform_obj = cform.save(commit=False)
cform_obj.student = sform_obj
cform_obj.save()
....

I figured it out.. My formset data was persisting after submission. I had to declare an empty queryset in the basemodelformset.

Related

Django - I want to store the data of 3 models into a single database in phpmyadmin (MySQL)

I have created 3 models (country, state and city) and the inputted data is getting stored in 3 different table. I want to store this data into a single table with following columns:
Database Column Schema
Models.py
class Country(models.Model):
id = models.AutoField(primary_key=True)
parent_id = models.IntegerField(null=False)
name = models.CharField(null=False, max_length=255)
status = models.CharField(null= True, choices=Status_Choices, max_length=11, default='--Select Status--')
added_by = models.IntegerField()
updated_by = models.IntegerField()
created_on = models.CharField(default=get_current_datetime_str , max_length=255)
updated_on = models.CharField(default=get_current_datetime_str, max_length=255)
def __str__(self):
return self.name
class State(models.Model):
parent = models.ForeignKey(Country, on_delete=models.CASCADE)
name = models.CharField(null=False, max_length=255)
def __str__(self):
return self.name
class City(models.Model):
Country = models.ForeignKey(Country, on_delete=models.CASCADE)
state = models.ForeignKey(State, on_delete=models.CASCADE)
name = models.CharField(null=False, max_length=255)
def __str__(self):
return self.name
admin.py
from django.contrib import admin
from location.models import Country, State, City
from django import forms
from django.contrib import admin
class CountryAdmin(admin.ModelAdmin):
exclude = ('parent_id', 'created_on', 'updated_on', 'added_by', 'updated_by')
def save_model(self, request, obj, form, change):
user = request.user
# Check if the user is authenticated (i.e. logged in)
if user.is_authenticated:
# If the user is authenticated, set the added_by field to the user's ID
obj.added_by = user.id
else:
# The user is not authenticated, do something else
...
if change:
obj.updated_by = user.id
# Save the model instance
super().save_model(request, obj, form, change)
admin.site.register(Country, CountryAdmin)
#admin.register(State)
class StateAdmin(admin.ModelAdmin):
# Define the fields to be displayed in the list view of states
list_display = ('name', 'parent')
# Set the heading for the states page in the Django admin interface
verbose_name_plural = 'Locations'
#admin.register(City)
class StateAdmin(admin.ModelAdmin):
# Define the fields to be displayed in the list view of states
list_display = ('name', 'state')
# Set the heading for the states page in the Django admin interface
verbose_name_plural = 'Locations'
forms.py
from django import forms
from .models import Country, State, City
class CountryForm(forms.ModelForm):
class Meta:
model = Country
fields = ['name']
def clean_name(self):
name = self.cleaned_data['name']
if name == '--Select Country--':
raise forms.ValidationError("Please select a valid country")
return name
class StateForm(forms.ModelForm):
class Meta:
model = State
fields = ['name', 'parent']
class CityForm(forms.ModelForm):
class Meta:
model = City
fields = ['name', 'state']
I tried merging them but for that i have to add extra column for city and state. I want everything to be stored under name corresponding to their parent id (refer database schema).

How to set a foreignkey field in views?

I'm trying to save the customer field on the Test model, I'm not getting any errors but it's not saving the field either, how do I fix it?
Models
class Test(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
email = models.EmailField(max_length=200, blank=False)
Forms
class TestForm(forms.Form):
email = forms.EmailField(required=True)
class Meta:
model = Test
fields = ("email")
def save(self, commit=False):
# Creating the customer object
Test.objects.create(email=self.cleaned_data['email'])
Views
def test_view(request):
customer = request.user.customer
if form.is_valid():
email = form.cleaned_data['email']
customer = customer
form.save()
You can use cleaned_data to save the ModelForm.
forms.py
class TestForm(forms.ModelForm):
class Meta:
model = Test
fields = ["email"]
Assuming, you have request method POST.
views.py
def test_view(request):
if request.method=="POST":
form=TestForm(request.POST)
customer = request.user.customer
if form.is_valid():
email = form.cleaned_data['email']
test=Test(customer=customer,email=email)
test.save()
You need to use a ModelForm, then save the object without commiting, edit the customer of the object, then commit.
class TestForm(forms.ModelForm):
class Meta:
model = Test
fields = ["email", ]
def test_view(request):
customer = request.user.customer #I'm not sure this line is right, but I can't see all your models
if form.is_valid():
test = form.save(commit=False)
test.customer = customer
test.save()

How to add manytomanyfield attributs with form instead select option field in Django?

info: I have two models customer and items model. customer has ManyToManyField items attribute. my Createview is working fine multiple items save in database while am creating new customer i am able to select multiple items in form. but
Problem: I want to add itemform attribute with customer form. I need when i create new customer i want to Save a new item with the new customer...
Model.py
class Item(models.Model):
name = models.CharField(max_length=255)
datetime = models.DateTimeField(auto_now_add=True)
amount = models.FloatField(default=0)
remaining = models.FloatField(default=0)
class Customer(models.Model):
name = models.CharField(max_length=255)
phone = models.CharField(max_length=11)
items = models.ManyToManyField(Items)
forms.py
class ItemForm(forms.ModelForm):
class Meta:
model = Installment
fields = '__all__'
class CustomerForm(forms.ModelForm):
class Meta:
model = Customer
fields = '__all__'
views.py
def customer_create_view(request):
if request.method == 'POST':
form = CustomerForm(request.POST)
items = ItemForm(request.POST)
if form.is_valid():
if items.is_valid():
items.save()
form.save()
return redirect("/")
else:
form = CustomerForm()
items = ItemForm()
context = {
'form': form,
'items': items
}
return render(request, 'customer/app.html', context)
You can revise your models by adding a CustomerItem model. This will handle all the records of items and customers that are related.
class Item(models.Model):
name = models.CharField(max_length=255)
datetime = models.DateTimeField(auto_now_add=True)
amount = models.FloatField(default=0)
remaining = models.FloatField(default=0)
class Customer(models.Model):
name = models.CharField(max_length=255)
phone = models.CharField(max_length=11)
class CustomerItem(models.Model):
item = models.ForeignKey(Item, related_name='items', on_delete=models.CASCADE)
customer = models.ForeignKey(Customer, related_name='customers', on_delete=models.CASCADE)
With this implementation, you can save whatever items you want to create while creating also customers.

Django modelform submission with relational data

I have a django modelform that creates a new listing in my post app, I would like to associate this with a company id, which is an account type in my account app.
The account_company db table (postgresql) has a user_id field which is the pk of User. the post_listing table will have a company field which I think should be the pk of account_company.
As I am attempting to use modelforms for all forms, I am having an issue with making this association.
# models.py
class Listing(models.Model):
title = models.CharField(max_length=200)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
...
# forms.py
class newListingForm(forms.ModelForm):
class Meta:
model = Listing
fields = ('title'...)
def __init__(self, user, *args, **kwargs):
super(newListingForm, self).__init__(*args, **kwargs)
self.fields['company'].queryset = Company.objects.filter(pk__user_id=user.id)
# above i am trying to filter the AutoField to the `company pk` where `user_id` is equal to `request.user.id`
# views.py
def post(request):
if request.method == 'POST':
form = newListingForm(request.user, request.POST)
if form.is_valid():
listing = form.save(commit=False)
listing.user = request.user
listing.save()
else:
form = newListingForm(request.user)
return render(request, 'post/post.html', {'form': form})
The debug error i get is:
Unsupported lookup 'user_id' for AutoField or join on the field not permitted.
Updated
#accounts model.py
...
class Company(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
photo = models.ImageField(upload_to='images/%Y/%m/%d/', null=True)
description = models.TextField(null=True)

How to get the foreign keys related to drop down only of that user in Django ModelForm

I have Category model like this:
class Task(models.Model):
'''
Task for the wedding plans
'''
description = models.CharField(max_length=128)
owner = models.ForeignKey(User, default="bride")
category = models.ForeignKey(Category)
class Category(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=128)
budget = models.DecimalField(default=0.0, decimal_places=2, max_digits=8, help_text="Amount in dollars ($)")
class Meta:
verbose_name_plural = "Categories"
In my forms.py:
class CategoryForm(ModelForm):
class Meta:
model = Category
exclude = ['user']
class TaskForm(ModelForm):
class Meta:
model = Task
exclude = ['owner']
# views
form = TaskForm()
When I call {{ form }} in template, it shows categories created by all the users. But I want to show the category created by only the logged in user. How to do that?
Try following:
form = TaskForm()
form.fields['owner'].queryset = Task.objects.filter(owner=request.user)
Or modify TaskForm as follow if it is used multiple times:
class TaskForm(ModelForm):
class Meta:
model = Task
exclude = ['owner']
def __init__(self, user, *args, **kwargs):
super(TaskForm, self).__init__(*args, **kwargs)
self.fields['owner'].queryset = Task.objects.filter(owner=user)
then, pass request.user:
form = TaskForm(request.user)

Categories