I have a trip model, and the form asks for a outbound flight and an inbound flight, that are both ForeignKeys.
How can I save the inbound flight as None, if no flight is selected and actually allow this form field to be empty.
This is my form:
class NewTrip(ModelForm):
def __init__(self, *args, **kwargs):
super(NewTrip, self).__init__(*args, **kwargs)
self.fields['trip_id'].widget = TextInput(attrs={'class': 'form-control'})
self.fields['destination'].widget = TextInput(attrs={'class': 'form-control'})
self.fields['client'].queryset = Clients.objects.all()
class Meta:
model = Trip
fields = ('trip_id', 'destination', 'client', 'out_flight', 'hotel', 'in_flight')
And this is my model:
class Trip(models.Model):
trip_id = models.CharField(max_length=20, verbose_name="Ref. Viagem")
destination = models.CharField(max_length=200, null=True, verbose_name='Destino')
client = models.ForeignKey(Clients, null=True, on_delete=models.CASCADE, verbose_name="Cliente")
out_flight = models.ForeignKey(Flight, related_name="outbound_flight" ,null=True, on_delete=models.SET_NULL, verbose_name="Voo Ida")
hotel = models.ForeignKey(Hotels, null=True, on_delete=models.SET_NULL, verbose_name="Hotel")
in_flight = models.ForeignKey (Flight, related_name="inbound_flight", null=True, on_delete=models.SET_NULL, verbose_name="Voo Regresso")
And this is the view:
def newtrip(request):
if request.method == 'POST':
form = NewTrip(request.POST)
if form.is_valid():
form.save()
return redirect('trips')
else:
form = NewTrip()
return render(request, 'backend/new_trip.html', {'form': form})
Add blank=True to your in_flight and out_flight
in_flight = models.ForeignKey(..., blank=True)
out_flight = models.ForeignKey(..., blank=True)
Related
I want to replicate the admin functionality shown in the screenshot below on the client side. This is app is meant to cost a recipe based on the ingredients and quantity.
Find below some snippets of my code
admin.py
class RecipeIngredientInline(admin.TabularInline):
model = RecipeIngredient
extra=0
class RecipeAdmin(admin.ModelAdmin):
inlines = [RecipeIngredientInline]
admin.site.register(Recipe, RecipeAdmin)
models.py
class Ingredient(models.Model):
ingredient_name = models.CharField(max_length=255)
unit_of_measure = models.CharField(max_length=255)
price = models.DecimalField(max_digits=20, decimal_places=2)
units_size_in_package = models.DecimalField(max_digits=20, decimal_places=2)
cost_per_unit = models.DecimalField(max_digits=20, decimal_places=2)
supplier = models.CharField(max_length=255, null=True, blank=True)
create_date = models.DateTimeField(auto_now_add=True, blank=True)
edit_date = models.DateTimeField(auto_now=True, blank=True)
class Recipe(models.Model):
recipe_name = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
photo = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True, null=True)
product_category = models.ForeignKey(ProductCategory, on_delete=models.SET_NULL, blank=True, null=True)
ingredients = models.ManyToManyField(Ingredient, through='RecipeIngredient')
is_vatable = models.BooleanField(default=False)
VAT_percentage = models.PositiveIntegerField(blank=True, null=True)
VAT = models.FloatField(blank=True, null=True)
create_date = models.DateTimeField(auto_now_add=True, blank=True)
edit_date = models.DateTimeField(auto_now=True, blank=True)
class RecipeIngredient(models.Model):
recipe = models.ForeignKey(Recipe, blank=True, null=True, on_delete=models.CASCADE)
ingredient = models.ForeignKey(Ingredient, blank=True, null=True, on_delete=models.CASCADE)
quantity = models.DecimalField(max_digits=20, decimal_places=2)
cost = models.FloatField(blank=True, null=True)
create_date = models.DateTimeField(auto_now_add=True, blank=True)
edit_date = models.DateTimeField(auto_now=True, blank=True)
forms.py
class RecipeForm(forms.ModelForm):
product_category = forms.ModelChoiceField(queryset=ProductCategory.objects.all())
class Meta:
model = Recipe
fields = ['recipe_name', 'description', 'photo', 'product_category', 'ingredients', 'is_vatable',
'VAT_percentage' ]
widgets = {
'description': forms.Textarea(
attrs={
'rows': 4,
}
),
'VAT_percentage': forms.NumberInput(
attrs={
'class': 'form-control',
}
),
}
)
class RecipeIngredientForm(forms.ModelForm):
ingredient = forms.ModelChoiceField(
queryset=Ingredient.objects.all(),
widget=forms.Select(attrs={'class': 'form-control'})
)
cost = forms.CharField(required = False)
class Meta:
Model = RecipeIngredient
fields=['ingredient', 'quantity', 'cost' ]
widgets = {
'quantity': forms.NumberInput(
attrs={
'class': 'form-control',
}
),
'cost': forms.NumberInput(
attrs={
'class': 'form-control',
}
),
}
RecipeIngredientFormset = inlineformset_factory(Recipe,
Recipe.ingredients.through,
form=RecipeIngredientForm,
extra=2,
can_delete=True
)
I am unable to add records to the parent and through table (Recipe and RecipeIngredient) so I suppose my view is not working fine. I have tried adapting the view in this question but it didn't work
Add row dynamically in django formset
My current idea shown below is also not working. I am stuck and need help on where I am going wrong with the view.
views.py
from .models import Recipe, RecipeIngredient
from .forms import RecipeForm, RecipeIngredientFormset
def recipe_create_view(request):
form = RecipeForm(request.POST or None, request.FILES or None)
formset = RecipeIngredientFormset(request.POST or None)
if form.is_valid() and formset.is_valid():
recipe = form.save(commit=False)
recipe.save()
for each_form in formset:
recipe_ingredient = each_form.save(commit=False)
if recipe_ingredient.recipe is None:
recipe_ingredient.recipe = recipe
recipe_ingredient.save()
return redirect('/costing/recipes')
context = {
'form': form,
'formset': formset,
}
return render(request, 'recipes/recipe_create.html', context)
def recipe_create_view(request):
form = RecipeForm(request.POST or None, request.FILES or None)
if request.POST and form.is_valid():
recipe = form.save(commit=False)
formset = RecipeIngredientFormset(request.POST, instance=recipe)
if formset.is_valid():
recipe.save()
formset.save()
return redirect('/costing/')
else:
formset = RecipeIngredientFormset(request.POST or None, instance=Recipe())
context = {
'form': form,
'formset': formset
}
return render(request, 'recipes/recipe_create.html', context)
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})
My process for this is for them to request an item through the project request view and is stored in the Activity model, if a request has been posted they can either approve or reject it using the request approve or request reject view. Now, I want to create a history table that automatically stores the approved or rejected status of a requested item after they approve/reject it, who approved/rejected it, when it was done.
Models.py
class Activity(models.Model):
Item = models.ForeignKey(Item, on_delete=models.CASCADE, null=True, limit_choices_to={'Quantity__gt': 0})
staff = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True, limit_choices_to={'Quantity__gt': 0})
project_site = models.ForeignKey(Projects, on_delete=models.CASCADE, null=True)
Quantity = models.PositiveIntegerField(null=True, default=1,
validators=[
MaxValueValidator(100),
MinValueValidator(1)
])
date_created = models.DateTimeField(auto_now_add=True)
is_draft = models.BooleanField(default=True)
request_status = models.IntegerField(default=0,
validators=[
MaxValueValidator(3)
])
return_status = models.IntegerField(default=0,
validators=[
MaxValueValidator(3)
])
note = models.TextField(max_length=255, null=True)
class Meta:
verbose_name_plural = 'Item Request'
def __str__(self):
return f'{self.Item}'
Views.py
def project_request(request):
activities = Activity.objects.all()
returns = ReturnItem.objects.all()
if request.method == 'POST':
form = ActivityForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.staff = request.user
instance.request_status = 2
instance.return_status = 2
instance.save()
return redirect('project_request')
else:
form = ActivityForm()
context={
'activities' : activities,
'returns' : returns,
'form' : form,
}
template_name ='project-admin/project-request-items.html'
return render(request, template_name, context)
def request_approve(request, pk):
activities = Activity.objects.get(id=pk)
activities.request_status = 1
activities.save()
return redirect('project_request')
def request_reject(request, pk):
activities = Activity.objects.get(id=pk)
activities.request_status = 0
activities.save()
return redirect('project_request')
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
I created an album with a photos as foreign key but somehow when i add a photo it does not save probably in my database or admin site
Here are my models:
class AlbumPluginModel(CMSPlugin):
name = models.CharField(max_length=255,
help_text=_('e.g: Zuerich city, or Zuerich Hoengg'))
slug = models.SlugField(_('Slug'), blank=True, null=True, unique=True, db_index=True)
description = HTMLField(blank=True, null=True)
cover_photo = models.ImageField(verbose_name=_('Add cover photo'), null=True, blank=True)
is_active = models.BooleanField(_('active'), blank=True)
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
sort = models.IntegerField(_("Sort Order"), null=True, blank=True, default=0)
def __str__(self):
if self.name:
return u"File for %s" % self.name
else:
return u"%s" % self.name
def get_absolute_url(self):
return "/album_detail%i/" % self.id
class Meta:
ordering = ['sort']
verbose_name = "Album"
verbose_name_plural = "Albums"
class Photo(models.Model):
photo = models.ForeignKey(AlbumPluginModel, verbose_name=_('choose album'), null=True, blank=True)
image1 = models.ImageField(verbose_name=_('Photo'), null=True, blank=True, upload_to="/static/img/")
sort = models.IntegerField(_("Sort Order"), null=True, blank=True, default=0)
def __unicode__(self):
return u"%s" % self.image1
def __str__(self):
return u"%s" % self.image1
class Meta:
ordering = ['sort']
verbose_name = _("photo")
verbose_name_plural = _("Photos")
forms.py
class AlbumPluginForm(forms.ModelForm):
class Meta:
model = AlbumPluginModel
fields = ['name', 'description', 'cover_photo', 'is_active',]
class PhotoPluginForm(forms.ModelForm):
photo = forms.ModelChoiceField(label='select album',aqueryset=AlbumPluginModel.objects.all(), required=False)
class Meta:
model = Photo
fields = ('photo', 'image1', )
views.py
def add_photo(request, id=None, **kwargs):
if request.method == 'POST':
all_photos = Photo.objects.all
form = PhotoPluginForm(request.POST, request.FILES, initial={'photo': id})
template_name = 'photo_create.html'
context = {
"form": form,
"all_photos": all_photos,
}
if form.is_valid():
all_photos = form.save(commit=False),
form.save()
messages.success(request, "Photo was added.")
return redirect('/photos')
else:
print("error: form nicht valid")
return render(request, template_name, context)
You should add upload_to parameter for field in which you want to upload some file in server. In your case, in AlbumPluginModel your cover_photo will be
cover_photo = models.ImageField(verbose_name=_('Add cover photo'), null=True, blank=True, upload_to='path_where_you_want_to_save')
If you call save() with commit=False, then it will return an object that hasn’t yet been saved to the database. In this case, it’s up to you to call save() on the resulting model instance. You should change your view like this
all_photos = form.save(commit=False),
all_photos.save()
after a long try i finally found the answer:
in views.py
i chnaged this line from
form = PhotoPluginForm(request.POST or None)
to:
form = PhotoPluginForm(request.POST, request.FILES)
and in my template i forgot this:
enctype="multipart/form-data"