how to set a default value in Django forms? - python

In the database there is class Borrowing which contains employee_id that will borrow item and tag_id (the item) and subscriber_id
in my code, if an employee request a borrowing, he can choose subscriber_id.
I need to set the subscriber_id to 1, without even asking the employee to choose.
in the models.py file
class Borrowing(models.Model):
borrowing_id = models.IntegerField(null=True)
start_date = models.DateField(auto_now_add=True, null=True)
end_date = models.DateField(null=True)
employee_id = models.ForeignKey(Employee, null=True, on_delete= models.SET_NULL)
tag_id = models.ForeignKey(Tag, null=True, on_delete= models.SET_NULL)
subscriber_id = models.ManyToManyField(Subscriber)
def __str__(self):
return str(self.borrowing_id)
in forms.py file
class BorrowingForm(ModelForm):
class Meta:
model = Borrowing
fields = ['end_date', 'employee_id', 'tag_id', 'subscriber_id']
in views.py
def createBorrowing(request, pk):
BorrowingFormSet = inlineformset_factory(Employee, Borrowing, fields=('end_date','tag_id','subscriber_id'))
employee = Employee.objects.get(id=pk)
formset = BorrowingFormSet(queryset=Borrowing.objects.none(), instance=employee)
if request.method == 'POST':
formset = BorrowingFormSet(request.POST, instance=employee)
if formset.is_valid():
formset.save()
return redirect('/login')
context = {'formset':formset}
return render(request, 'assetstracking/createBorrowing.html', context)

You must set a default value in the Models.py
class Borrowing(models.Model):
...
subscriber_id = models.ManyToManyField(Subscriber, default=default_subscriber)
...
def __str__(self):
return str(self.borrowing_id)
And if you don't need the employee to chose you can remove subscriber_id from the fields in the forms.py
Notice that default_subscriber needs to be a subscriber.

Related

How to pass parameter into the Form?

I have a form class (incorrect) :
class TeamGoalForm(ModelForm):
class Meta:
employees = forms.ModelMultipleChoiceField(queryset=Employee.objects.filter(departament=Department.objects.get(manager=Manager.objects.get(end_user_id = request.user.username.upper())),widget=forms.CheckboxSelectMultiple()))
department = forms.ModelChoiceField(queryset=Department.objects.all())
model = TeamGoal
fields = '__all__'
widgets = {
'employees' : forms.Select(attrs={'class': 'form-control', 'placeholder':'Select employees'}),
}
'department':forms.Select(attrs={'class': 'form-control', 'placeholder':'Select department'}),
I want to pass parameter request.user.username.upper() which I have in my view.py. How to implement this in my TeamGoalForm?
my view.py
#login_required(login_url='login')
def add_team_goal(request):
form = TeamGoalForm(is_manager(request))
if request.method == 'POST':
form = TeamGoalForm(request.POST)
if form.is_valid():
form.save()
return redirect('team_goal')
team = get_team(request)
if team.exists():
return render(request, 'smth.html', {'form':form,'team':team})
My Employee model:
# Employee section
class Employee(models.Model):
name = models.CharField(max_length=30, verbose_name='Name')
lastname = models.CharField(max_length=30, verbose_name='Lastname')
.............
history = HistoricalRecords()
def __str__(self):
return self.name + ' ' + self.lastname
My Department:
class Department(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=30)
.........
manager = models.ForeignKey(Manager, related_name='manager_name', null=True, on_delete = models.SET_NULL)
history = HistoricalRecords()
My Managers:
class Manager(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30)
lastname = models.CharField(max_length=30)
history = HistoricalRecords()
def __str__(self):
return self.name + ' ' + self.lastname
My TeamGoal:
class TeamGoal(models.Model):
team_goal_title = models.CharField(max_length=30, verbose_name='Title')
team_goal_description = models.CharField(max_length=100, blank=True, verbose_name='Description')
department = models.ForeignKey(Department, verbose_name='Department', on_delete = models.CASCADE, related_name='+', blank=True, null=True, help_text=u'If you assign the team goal for the whole department, please fill only Department field and skip Employee field.')
employees = models.ManyToManyField(Employee, null=True, blank=True, symmetrical=False, related_name='employee_name')
......
history = HistoricalRecords()
In my app I can create Team goal for whole department or for specific group of employees.
I would really advise not to give Manager the same name as a user and then match on that: it makes keeping records in sync quite hard. You can link to the user model with:
from django.conf import settings
class Manager(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
history = HistoricalRecords()
def __str__(self):
return f'{self.user.first_name} {self.user.lastname}'
you can pass the user as parameter to the ModelForm and then filter the queryset:
class TeamGoalForm(ModelForm):
def __init__(self, *args, user=None, **kwargs):
super().__init_(*args, **kwargs)
if user is not None:
self.field['employees'] = Employee.objects.filter(
department__manager__user=user
)
class Meta:
model = TeamGoal
fields = '__all__'
widgets = {
'employees' : forms.SelectMultiple(attrs={'class': 'form-control', 'placeholder':'Select employees'}),
'department':forms.SelectMultiple(attrs={'class': 'form-control', 'placeholder':'Select department'})
}
and in the view pass the logged in user to the TeamGoalForm:
#login_required(login_url='login')
def add_team_goal(request):
if request.method == 'POST':
form = TeamGoalForm(request.POST, user=request.user)
if form.is_valid():
form.save()
return redirect('team_goal')
else:
form = TeamGoalForm(user=request.user)
team = get_team(request)
return render(request, 'smth.html', {'form':form,'team':team})

Direct assignment to the forward side of a many-to-many set is prohibited. Use product.set() instead

i'm building a small webstore , in the product page i put the order form using FormMixin and TemplateView, when i submit the order i get a "Direct assignment to the forward side of a many-to-many set is prohibited. Use product.set() instead." error
Bellow you can check the code
Models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=255, unique=True, )
description = models.TextField(max_length=1500)
class Meta:
verbose_name_plural = "categories"
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
nominal_price = models.PositiveIntegerField(verbose_name='prix normal',)
reduced_price = models.PositiveIntegerField(blank=True, null=True)
quantity = models.PositiveIntegerField(default=10)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='products')
photo = models.ImageField(upload_to="img/products/", default="img/products/user_default.png")
def __str__(self):
return self.name
class Customer(models.Model):
full_name = models.CharField(max_length=150)
address = models.CharField(max_length=1500, null=True)
phone = models.IntegerField()
city = models.CharField(max_length=100)
email = models.EmailField(null=True)
class Order (models.Model):
product = models.ManyToManyField(Product, through='OrderProduct')
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
class OrderProduct(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
Views.py
class ProductDetailView(FormMixin, TemplateView):
model = Product
template_name = 'product.html'
form_class = OrderForm
def get_success_url(self):
return reverse('index')
def post(self, request, *args, **kwargs):
context = self.get_context_data()
form = OrderForm(request.POST)
if context['form'].is_valid():
product = get_object_or_404(Product, name=self.kwargs['product_name'])
customer = form.save()
Order.objects.create(product=product, customer=customer)
return super(TemplateView, self)
def get_context_data(self, **kwargs):
context = super(ProductDetailView, self).get_context_data(**kwargs)
context['product'] = Product.objects.get(name=self.kwargs['product_name'])
context['form'] = self.get_form()
return context
urls.py
path('', views.ProductListView.as_view(), name='index'),
Did i missed something
For handling many-to-many relations, you cannot directly set the product from Order. Also you would need to create the order first before you can set or add a product:
order = Order.objects.create(customer=customer)
order.product.add(product)

Matching query does not exist when update view is called in django

I have a custom user model from AbstractBaseUser and BaseUserManager. The user model is extended to a model called Employee. The employee model is related with(Foreignkey) two other model named WorkExperience and education. A single template form is designed with Employee, WorkExperience and Education modelform.
models.py:
class Employee(models.Model):
"""
Create employee attributes
"""
employee_user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
e_id = models.IntegerField(unique=True, null=True)
first_name = models.CharField(max_length=128, null=True)
last_name = models.CharField(max_length=128, null=True)
gender_choices = (
('Male', 'Male'),
('Female', 'Female'),
)
......
#receiver(post_save, sender=UserProfile)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Employee.objects.create(employee_user=instance, email=instance.email)
instance.employee.save()
class WorkExperience(models.Model):
"""
Stores employee previous work experiences
"""
employee_user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
employee = models.ForeignKey('Employee', related_name='we_employee', on_delete=models.CASCADE, null=True)
previous_company_name = models.CharField(max_length=128, null=True)
job_designation = models.CharField(max_length=128, null=True)
from_date = models.DateField(null=True)
to_date = models.DateField(null=True)
job_description = models.CharField(max_length=256, null=True)
class Education(models.Model):
"""
Stores employee education background
"""
employee_user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
employee = models.ForeignKey('Employee', related_name='edu_employee', on_delete=models.CASCADE, null=True)
institution_name = models.CharField(max_length=128, null=True)
degree = models.CharField(max_length=128, null=True)
passing_year = models.IntegerField(null=True)
result = models.DecimalField(max_digits=5, decimal_places=2, null=True)
I have a CreateView of this three models. I have three modelform. I implemented CRUD using this modelforms. My problem is in UpdateView. When I call UpdateView an error is showing stating WorkExperience matching query does not exist.I think the query is not correct.
views.py:
class EmployeeUpdateView(LoginRequiredMixin, UpdateView):
"""
Update a created a employee
"""
login_url = '/authentication/login/'
template_name = 'employee/employee_update_form.html'
form_class = EmployeeAddModelForm
work_form_class = WorkExperienceForm
education_form_class = EducationForm
context_object_name = 'employee'
model = Employee
queryset = Employee.objects.all()
# Override default get method
def get(self, request, *args, **kwargs):
id_ = self.kwargs.get("id")
employee_id = Employee.objects.get(id=id_)
work_info = WorkExperience.objects.get(employee=employee_id)
education_info = Education.objects.get(employee=employee_id)
form = self.form_class(instance=employee_id)
work_form = self.work_form_class(prefix='work_form', instance=work_info)
education_form = self.education_form_class(prefix='education_form',instance=education_info)
return render(request, self.template_name, {
'form': form,
'work_form': work_form,
'education_form': education_form,
'supervisor_assigned': employee_id.supervisor_select
}
)
# Override default post method
def post(self, request, *args, **kwargs):
id_ = self.kwargs.get("id")
employee_id = Employee.objects.get(id=id_)
work_info = WorkExperience.objects.get(employee=employee_id)
education_info = Education.objects.get(employee=employee_id)
form = self.form_class(request.POST, instance=employee_id)
work_form = self.work_form_class(request.POST, prefix='work_form', instance=work_info)
education_form = self.education_form_class(request.POST, prefix='education_form',instance=education_info)
# Check form validation
if form.is_valid() and work_form.is_valid() and education_form.is_valid():
instance = form.save()
work = work_form.save(commit=False)
education = education_form.save(commit=False)
work.employee = instance
education.employee = instance
work.save()
education.save()
return redirect('employee:employee-list')
return render(request, self.template_name, {
'form': form,
'work_form': work_form,
'education_form': education_form
}
)
urls.py:
urlpatterns = [
path('employee-list/', EmployeeListView.as_view(), name='employee-list'),
path('employee-add/', EmployeeAddView.as_view(), name='employee-add'),
path('employee-list/<int:id>/', EmployeeDetailView.as_view(), name='employee-detail'),
path('employee-list/<int:id>/update/', EmployeeUpdateView.as_view(), name='employee-update'),
How can I modify my query? i think my query is not correct.
you need to use foreign Key to use the employee id :
work_info = WorkExperience.objects.get(employee__id=employee_id)
I Hope it works fine

IntegrityError at * UNIQUE constraint failed

I am trying to create a django application to keep track of a product(product stock application).whenever I try to add new product ,I cannot add more than one product in the same category. It gives UNIQUE constraint failed error .
I want to add multiple products in same category.
models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=100)
slug = models.CharField(max_length=100)
price = models.DecimalField(max_digits=6, decimal_places=2)
quantity = models.IntegerField(null=True, blank=True)
category = models.ForeignKey(
Category, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Stock(models.Model):
sold_quantity = models.IntegerField(null=True, blank=True)
product = models.ForeignKey(Product, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.product.name
Edit:
Views
def createProduct(request):
form = AddProductForm()
if request.method == 'POST':
form = AddProductForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
contex = {'form': form}
return render(request, 'stockmgmt/add_products.html', contex)
Forms.py
class AddProductForm(ModelForm):
class Meta:
model = Product
fields = '__all__'
Error Message

Specific user content Add, Edit, Delete particular data for particular user

I'm starting to organize a project with a few models, but the two main models in question are Brands and Products.
I will allow clients to login on Django Admin site to edit their Brands and to Add, Edit and Delete their own Products.
However when editing their Products, said client will only be able to Add, Edit & Delete their own Products; so for example their Brand Name will already be chosen in the Foreign Key dropdown, due to the permission constrain. From there they can repeat the process of adding their Brands and Delete and Edit the Brands as they Choose.
Current Setup & Problem
Currently I have this setup for Brands the way I would like, just for a client to see only their Brands to Edit. But for Products, they can see all the products, even for different Brands (which is not what I want); and when they create a new product they have to choose from a dropdown of products to match with (which is not what I want). I am using the default Django permissions as of now, with some ModelAdmin methods.
models.py
class TimeStampedModel(models.Model):
"""
An abstract base class model that provides self updating
``created`` and ``modified`` fields.
"""
created = models.DateTimeField(auto_now_add=True, blank=True, null=True)
modified = models.DateTimeField(auto_now=True, blank=True, null=True)
# Metadata
class Meta:
abstract = True
class Brand(TimeStampedModel):
"""
Information for each brand
"""
# Primary Key
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# General information
brand_name = models.CharField(max_length=100, blank=True, default="", unique=True)
brand_description = models.TextField(max_length=100, blank=True, default="")
brand_origin_city = models.CharField(max_length=100, blank=True, default="")
brand_origin_state_or_country = models.CharField(max_length=100, blank=True, default="",
help_text=_('State (USA only), Country (International only)'), verbose_name=_('State or Country'))
brand_feature_image = CloudinaryField('Featured Brand Image', null=True, blank=True)
brand_isActive = models.BooleanField(default=False, verbose_name=_('Brand active'))
# Metadata
class Meta:
verbose_name = _('Brand')
verbose_name_plural = _('Brands')
def __unicode__(self):
return "{0}".format( self.brand_name )
class Product(TimeStampedModel):
"""
Product for each brand
"""
product_name = models.CharField(max_length=100, blank=True, default="", verbose_name=_('Product Name') )
product_url = models.URLField(max_length=100, blank=True, default="",
help_text=_('This is for the product web url to the particular item on your website.'), verbose_name=_('Product Url'))
product_price = CurrencyField( verbose_name=_('Product price') )
product_image = CloudinaryField('Product Image', blank=True, null=True)
# Foreign Key
brand = models.ForeignKey('Brand', null=True, to_field="id")
#Metadata
class Meta:
verbose_name = _('Product')
verbose_name_plural = _('Products')
def __unicode__(self):
return "{0}".format( self.product_name )
Admin.py
class BrandAdmin(admin.ModelAdmin):
list_display = ["brand_name", "brand_origin_city", "brand_origin_state_or_country"]
search_fields = ["brand_name"]
list_per_page = 10
def save_model(self, request, obj, form, change):
obj.user = request.user
super(BrandAdmin, self).save_model(request, obj, form, change)
obj.save()
def get_queryset(self, request):
qs = super(BrandAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(brand_name=request.user)
class ProductAdmin(admin.ModelAdmin):
list_display = ["product_name","product_price"]
search_fields = ["product_name"]
list_per_page = 20
def save_model(self, request, obj, form, change):
obj.user = request.user
super(ProductAdmin, self).save_model(request, obj, form, change)
obj.save()
def get_queryset(self, request):
qs = super(ProductAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(brand=request.user)
# Register Models below
admin.site.register(Brand, BrandAdmin)
admin.site.register(Product, ProductAdmin)
What would be a solution to solve this issue?
class ProductAdmin(admin.ModelAdmin):
...
def get_queryset(self, request):
...
return qs.filter(brand__brand_name = request.user)
Hope this work. Let me know if not.

Categories

Resources