Another question from me tonight and I hope I can explain it adequately:
I got three classes in my "models.py":
class Customer(models.Model):
full_name = models.CharField(max_length=100, null=True, unique=True)
short_name = models.CharField(max_length=8, null=True, unique=True)
class Project(models.Model):
customer = models.ForeignKey(Customer, null=False, on_delete=models.CASCADE)
name = models.CharField(max_length=255, null=True, unique=True)
...
class Entry(models.Model):
user = models.ForeignKey(User, null=True, blank=False, on_delete=models.CASCADE)
customer = models.ForeignKey(Customer, null=True, blank=False, on_delete=models.CASCADE)
project = models.ForeignKey(Project, null=True, blank=False, on_delete=models.CASCADE)
date = models.DateField()
shortText = models.CharField(max_length=100, null=False, blank=False)
...
Note: One Customer can have multiple Projects.
On one of my sites there's a table with buttons beside each "Customer". The plan is, that it should lead me to another page, were the user can write and save his "Entry". Right now, the PrimaryKey inside the Button/Link contains the ID of the "Customer".
My question is: is it possible to limit the choices of the "Project" (inside a Drop-Down-Menu) to the "Customer" that has been clicked on? And is creating a ModelForm the right thing to do?
Thanks to all of you and a good night!
Well, don't know if this is the right way, but I found a solution for my problem:
Wrote a "forms.ModelForm" for my view-function...
class EntryForm(ModelForm):
class Meta:
model = Entry
fields = '__all__'
def __init__(self, *args, pk, **kwargs):
super().__init__(*args, **kwargs)
self.fields['project'].queryset = Project.objects.filter(customer_id=pk)
Insert my ModelForm into the view-function...
def WriteEntry(request, pk):
form = EntryForm(pk=pk)
if request.method =='POST':
form = EntryForm(request.POST, pk)
if form.is_valid():
form.save()
...
context = {'form': form}
return render(request, '...html', context)
Related
I am new to django and I created this "apply now form" exclusively for tutors that when they submit the form it will appear to the admin site, and I will manually check it if they are a valid tutor. And if they are a valid tutor, I will check the is_validated booleanfield in the admin site to the corresponding tutor that sent the form, so that he/she will have access to other things in the site. But I am having this problem that when you submit the form this comes up..
NOT NULL constraint failed: account_tutorvalidator.user_id
I have search for some solutions and also read similar questions here but I still couldn't understand what to do.. could someone help me out with this?
here is my models.py
class User(AbstractUser):
is_student = models.BooleanField(default=False)
is_tutor = models.BooleanField(default=False)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
phone_number = models.CharField(max_length=11, blank=False, null=True)
current_address = models.CharField(max_length=100, null=True)
image = models.ImageField(default='default-pic.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.first_name} {self.last_name}'
class TutorProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True,
related_name='tutor_profile')
bio = models.CharField(max_length=255, blank=True)
is_validated = models.BooleanField(default=False)
def __str__(self):
return f"{self.user.first_name} {self.user.last_name}'s Profile"
class TutorValidator(models.Model):
user = models.ForeignKey(TutorProfile, on_delete=models.CASCADE)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
dbs = models.ImageField(upload_to='dbs_pics')
driving_license = models.ImageField(upload_to='drivers_license_pics', null=True, blank=True)
national_id = models.ImageField(upload_to='national_id_pics', null=True, blank=True)
def __str__(self):
return f"{self.first_name}'s application form"
my forms.py
class TutorValidationForm(forms.ModelForm):
class Meta:
model = TutorValidator
fields = ['first_name', 'last_name', 'driving_license', 'national_id']
labels = {
'national_id': _('National ID')
}
my views.py
class TutorValidatorView(LoginRequiredMixin, FormView):
template_name = 'account/tutor_validator.html'
form_class = TutorValidationForm
success_url = '/'
The error is because TutorValidator requires that you set the user profile foreign key which your form currently does not support, so you need a way to set this to the object you are creating, and use the current logged in user (the one who is submitting the form).
You can do this by overriding form_valid. Try with:
class TutorValidatorView(LoginRequiredMixin, FormView):
...
def form_valid(self, form):
tutor_validator = form.save(commit=False)
tutor_validator.user = self.request.user.tutor_profile
tutor_validator.save()
return HttpResponseRedirect(self.get_success_url())
Note that the current user needs to already have an existing TutorProfile. Otherwise you need to create that first to connect it to TutorValidator
Hello everyone I'm trying top build a task manager web app using django, I need to assign task to one or multiple users I'm using manytomany relation in models.py and in views.py I'm adding created_by user automatically.
My problem is that when I do that I see that no users selected in assigned users but if I add created by user from the form it worked well.
class Task(models.Model):
task_id = models.AutoField(primary_key=True)
shortcode = models.CharField(max_length=15, unique=True, blank=True, null=True)
task_name = models.CharField(max_length=200)
task_progress = models.ForeignKey(TaskProgressStatus, on_delete=models.CASCADE, blank=True, null=True)
customer_name = models.ForeignKey(Customer, on_delete=models.CASCADE, blank=True, null=True)
task_priority = models.ForeignKey(TaskPriority, on_delete=models.CASCADE)
assigned_to_employee = models.ManyToManyField(User)
paid = models.BooleanField(default=False)
on_account = models.BooleanField(default=False)
currency = models.ForeignKey(Currency, on_delete=models.CASCADE, blank=True, null=True)
net_amount = models.DecimalField(decimal_places=2, max_digits=20, blank=True, null=True)
vat = models.IntegerField(default=11)
quote_validity = models.CharField(max_length=200, default='1 Month from offer date')
delivered = models.BooleanField(default=False)
delivered_date = models.DateTimeField(null=True, blank=True)
creation_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
due_date = models.DateTimeField(null=True, blank=True)
created_by = models.ForeignKey(User, related_name='created_by_username', on_delete=models.CASCADE, null=True, blank=True)
project = models.ForeignKey(Project, null=True, blank=True, on_delete=models.CASCADE)
file_name = models.FileField(upload_to='projects_files', null=True, blank=True)
notes = models.TextField()
def __str__(self):
return str(self.task_name)
#login_required
def addtask(request):
form = taskForm()
if request.method == 'POST':
form = taskForm(request.POST)
if form.is_valid():
newform = form.save(commit=False)
newform.created_by = request.user
newform.save()
return HttpResponseRedirect(request.path_info)
else:
context = {'form':form}
return render(request, 'tasks/add_task.html', context)
Update
As well pointed out by Ahmed I. Elsayed there is some inconsistency in the title of the question, since the created_by field is actually a ForeignKey, not a ManyToManyField.
That being said, your issue is actually with the foreign key.
My suggestion is to first of all be sure that your form is actually valid. You can do that by printing something inside the if form.is_valid() block.
i am trying to build my first project, a CRM website to handle orders and inventory.
and i got stuck, i was able to link orders to customer.
but when i try to build order that contain multi items. for some reason i didn't find a way to do it.
hope you can assist me.
so I have User>>Order>>Multi Items.
questions:
1) does the best practice here is just use ForeignKey ?
this my model's code:
from django.db import models
class Customer(models.Model):
name = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
def date_createdview(self):
return self.date_created.strftime('%B %d %Y')
class Product(models.Model):
CATEGORY = (
('General', 'General'),
('SmartHome', 'SmartHome'),
('Software', 'Software'),
('Mobile', 'Mobile'),
)
name = models.CharField(verbose_name='שם', max_length=200, null=True)
price = models.FloatField(verbose_name='מחיר', null=True)
category = models.CharField(max_length=200, null=True, choices=CATEGORY, verbose_name='קטגוריה')
description = models.CharField(max_length=200, null=True, verbose_name='מלל חופשי')
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Order(models.Model):
STATUS = (
('New', 'New'),
('Work in progress', 'Work in progress'),
('completed', 'completed'),
)
customer = models.ForeignKey(Customer, null=True, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True, null=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
def date_createdview(self):
return self.date_created.strftime('%d/%m/%Y')
class OrderItem(models.Model):
product = models.ForeignKey(Product, null=True, on_delete=models.CASCADE)
order = models.ForeignKey(Order, null=True, on_delete=models.CASCADE)
quantity = models.IntegerField(null=True)
2)how should I build my views or forms?
i want to make it dynamic, when i enter the order i can insert items and see the new item get add to a list of the items in the order.
how can save the order number and add new items?
this is my product view, it's working. I can add new products.
#login_required(login_url="login")
def products(request):
form = ProductForm(request.POST or None)
if form.is_valid():
form.save()
products = Product.objects.all()
context = {'form': form, 'products': products}
return render(request, 'accounts/products.html', context)
hope you can direct me to the right place.
thank you!
if form.is_valid():
order = get_object_or_404(Order, id=id)
instance = form.save(commit=False)
instance.order=order
instance.save()
just need to do:
commit=False
and then link the order.
I have 2 models, Item and OnHand. Item represents the product, like a USB Keyboard, while OnHand represents an actual USB Keyboard.
class Item(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=100)
manufacturer = models.ForeignKey(Manufacturer, blank=True, null=True, on_delete=models.SET_NULL)
category = models.ForeignKey(Category, blank=True, null=True, on_delete=models.SET_NULL)
vendor = models.ForeignKey(Vendor, blank=True, null=True, on_delete=models.SET_NULL)
vendor_sku = models.CharField(max_length=80, default='000000000')
replenish_threshold = models.IntegerField(max_length=1000, default=10)
max_onhand = models.IntegerField(max_length=10000, default=30)
introduction = models.DateField(auto_now=True)
tags = models.ManyToManyField(Tag)
slug = models.SlugField(max_length=100, default=slugify(name))
class Meta:
verbose_name_plural = 'items'
def __str__(self):
return self.name
class OnHand(models.Model):
name = models.CharField(max_length=100)
serial = models.CharField(max_length=80, default='Consumable')
asset = models.CharField(max_length=20, null=True, blank=True)
product = models.ForeignKey(Item, blank=True, null=True, on_delete=models.CASCADE)
tags = models.ManyToManyField(Tag)
class Meta:
verbose_name_plural = 'items on hand'
def __str__(self):
if not self.serial:
return self.name
return self.serial
I have a ModelForm I use for adding new Items and OnHand, the form I'm working with is at /inventory/add_onhand// so /inventory/add_onhand/1/ would be the form to add a keyboard to inventory for Item with a primary key of 1.
class OnHandForm(forms.ModelForm):
class Meta:
model = OnHand
fields = {'name', 'asset', 'serial',}
def add_onhand(request, query):
if request.method == "POST":
form = OnHandForm(request.POST)
if form.is_valid():
form.save()
return redirect('view_item')
else:
print(query)
form = OnHandForm()
item = Item.objects.get(pk=query)
return render(request, 'add_onhand.html', {'form':form, 'item':item})
When saving a new OnHand via this form, how would I direct the relationship to Item?
I am still hoping for a better solution, but in the meantime what I've done was added product to the form, but using JQuery to hide the element and automatically select it based on the Item's primary key.
This is hacky, but it works. I'd hope for a more elegant solution.
I have a Django 'add business' view which adds a new business with an inline 'business_contact' form.
The form works fine, but I'm wondering how to write up the unit test - specifically, the 'postdata' to send to self.client.post(settings.BUSINESS_ADD_URL, postdata)
I've inspected the fields in my browser and tried adding post data with corresponding names, but I still get a 'ManagementForm data is missing or has been tampered with' error when run.
Anyone know of any resources for figuring out how to post inline data?
Relevant models, views & forms below if it helps. Lotsa thanks.
MODEL:
class Contact(models.Model):
""" Contact details for the representatives of each business """
first_name = models.CharField(max_length=200)
surname = models.CharField(max_length=200)
business = models.ForeignKey('Business')
slug = models.SlugField(max_length=150, unique=True, help_text=settings.SLUG_HELPER_TEXT)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
phone = models.CharField(max_length=100, null=True, blank=True)
mobile_phone = models.CharField(max_length=100, null=True, blank=True)
email = models.EmailField(null=True)
deleted = models.BooleanField(default=False)
class Meta:
db_table='business_contact'
def __unicode__(self):
return '%s %s' % (self.first_name, self.surname)
#models.permalink
def get_absolute_url(self):
return('business_contact', (), {'contact_slug': self.slug })
class Business(models.Model):
""" The business clients who you are selling products/services to """
business = models.CharField(max_length=255, unique=True)
slug = models.SlugField(max_length=100, unique=True, help_text=settings.SLUG_HELPER_TEXT)
description = models.TextField(null=True, blank=True)
primary_contact = models.ForeignKey('Contact', null=True, blank=True, related_name='primary_contact')
business_type = models.ForeignKey('BusinessType')
deleted = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
address_1 = models.CharField(max_length=255, null=True, blank=True)
address_2 = models.CharField(max_length=255, null=True, blank=True)
suburb = models.CharField(max_length=255, null=True, blank=True)
city = models.CharField(max_length=255, null=True, blank=True)
state = models.CharField(max_length=255, null=True, blank=True)
country = models.CharField(max_length=255, null=True, blank=True)
phone = models.CharField(max_length=40, null=True, blank=True)
website = models.URLField(null=True, blank=True)
class Meta:
db_table = 'business'
def __unicode__(self):
return self.business
def get_absolute_url(self):
return '%s%s/' % (settings.BUSINESS_URL, self.slug)
VIEWS:
def business_add(request):
template_name = 'business/business_add.html'
if request.method == 'POST':
form = AddBusinessForm(request.POST)
if form.is_valid():
business = form.save(commit=False)
contact_formset = AddBusinessFormSet(request.POST, instance=business)
if contact_formset.is_valid():
business.save()
contact_formset.save()
contact = Contact.objects.get(id=business.id)
business.primary_contact = contact
business.save()
#return HttpResponse(help(contact))
#business.primary = contact.id
return HttpResponseRedirect(settings.BUSINESS_URL)
else:
contact_formset = AddBusinessFormSet(request.POST)
else:
form = AddBusinessForm()
contact_formset = AddBusinessFormSet(instance=Business())
return render_to_response(
template_name,
{
'form': form,
'contact_formset': contact_formset,
},
context_instance=RequestContext(request)
)
FORMS:
class AddBusinessForm(ModelForm):
class Meta:
model = Business
exclude = ['deleted','primary_contact',]
class ContactForm(ModelForm):
class Meta:
model = Contact
exclude = ['deleted',]
AddBusinessFormSet = inlineformset_factory(Business,
Contact,
can_delete=False,
extra=1,
form=AddBusinessForm,
)
The problem is you have not included the management form in your data. You need to include form-TOTAL_FORMS (total number of forms in the formset, default is 2), form-INITIAL_FORMS (the initial number of forms in the formset, default is 0) and form-MAX_NUM_FORMS (the maximum number of forms in the formset, default is '').
See the Formset documentation for more information on the management form.