Problem in displaying objects from ForeignKey in Django - django

I am having two models Patient and Ipd, Patient can have multiple Ipd. I am trying to get Patient Info in IpdForm but don't know where I am getting wrong
I have already tried "qs = Ipd.objects.get(patient__id=patient_id)" , "qs = Ipd.objects.filter(patient__id=patient_id)" but nothing worked
models.py :
class Patient(models.Model):
name = models.CharField(max_length=200);
phone = models.CharField(max_length=20);
address = models.TextField();
Patient_id = models.AutoField(primary_key=True);
Gender= models.CharField(choices=GENDER, max_length=10)
consultant = models.CharField(choices=CONSULTANT, max_length=20)
def __str__(self):
return self.name
class Ipd(models.Model):
reason_admission = models.CharField(max_length=200, blank=False)
presenting_complaints = models.CharField(max_length=200,)
ipd_id = models.AutoField(primary_key=True)
rooms = models.ForeignKey(Rooms,on_delete=models.CASCADE, blank=False)
date_of_admission = models.DateField(("Date"),
default=datetime.date.today)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE, blank=False, default = "")
def __str__(self):
return self.patient.name
forms.py :
class PatientForm(forms.ModelForm):
class Meta:
model = Patient
fields = ['name','phone','address','Patient_id','consultant','Gender']
class IpdForm(ModelForm):
class Meta:
model = Ipd
fields = ['patient', 'reason_admission', 'presenting_complaints',
'rooms', 'date_of_admission']
views.py:
#login_required
def ipd (request,patient_id):
formtwo = IpdForm()
qs = Ipd.objects.filter(patient__Patient_id=patient_id)
if request.method=="POST":
formtwo = IpdForm(request.POST)
if formtwo.is_valid() :
instance = formtwo.save(commit=False)
instance.save
else:
return HttpResponse(formtwo.errors)
else:
formtwo = IpdForm()
return render(request, 'newipd.html', {'a':qs,'form2':formtwo})
urls.py :
url(r'^order/ipd/(?P<patient_id>\d+)/$', my_order.ipd, name='ipd'),
html :
<div class="card-panel">
<span class="blue-text text-darken-2">Name : {{ab.name}}</span> <br>
<span class="blue-text text-darken-2">Phone : {{ a.phone }}</span><br>
<span class="blue-text text-darken-2">Address : {{ a.address }}</span><br>
<span class="blue-text text-darken-2">Gender : {{ a.Gender }}</span><br>
</div>

You can simply access your Patient model by using
Ipd.objects.filter(patient_id=patient_id)
Note the single underscore at the first patient_id.
You only use double underscores while accessing a related model, but in this case you have a foreign key directly in your Ipd model.
Edit
I just saw, that you created your own Patient_Id field.
I would suggest to recreate your Patient model without the field Patient_id.
Django will create an ID field itself.
If you really want to keep your own field, than the correct access to it would be:
Ipd.objects.filter(patient_patient_id=patient_id)
But I would not recommend that.
There are a lot more flaws in your code, like keeping all fields lowercase in a model, etc.
Please try to refer to the Django docs and maybe Python docs.
Keeping you code clear would simplify a lot of things.

Related

Django: Add a new value to ModelChoiceField

I have a ModelChoiceField in a form that uses a TextInput widget. I want to be able to select a value from the database or add new entries to the database with this input. If the value is not already in the database, I get an error on the form that says "Select a valid choice. That choice is not one of the available choices."
Model
class FeedCategory(models.Model):
category = models.CharField(max_length=255, unique=True)
class RssFeed(models.Model):
category = models.ForeignKey(FeedCategory, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=255)
feed = models.URLField()
Form
class RssForm(forms.Form):
name = forms.CharField()
feed = forms.URLField()
category = forms.ModelChoiceField(queryset=FeedCategory.objects.all(), to_field_name='category', widget=forms.TextInput())
def clean(self):
cleaned_data = super().clean()
????
Views
class RssCreateView(FormView):
template_name = 'dashboard/rss_feed_form.html'
form_class = RssForm
success_url = '/dashboard/'
def form_valid(self, form):
name = form.cleaned_data['name']
feed = form.cleaned_data['feed']
category = form.cleaned_data['category']
rss_obj = RssFeed(category=category, name=name, feed=feed)
rss_obj.save()
return super().form_valid(form)
Template
<form method="post">
{%csrf_token%}
{{form|crispy}}
<button type="submit">Save</button>
</form>
It might help you what I am using:
category = models.ForeignKey("General.entity",verbose_name='Category', db_column="CategoryEntityRef", null=False, blank=False)
so, what I am doing with this is creating a field that points to an existing category that exists in another table. It will display it as a dropdown box. However using this method will allow me to have the option to add another Category:

Create Single Forms by Two Models in Django with Dynamic Fields

I want to create Django Forms to save transactions for the store. I want a final template similar to this. The ER Diagram for my database is also shown in the image.
My Django Models are:
class Party(models.Model):
party_id = models.BigAutoField(primary_key=True)
party_name = models.CharField(max_length=128)
party_phone = models.CharField(max_length=128)
party_address = models.CharField(max_length=128)
def __str__(self):
return self.party_name
class Items(models.Model):
item_no = models.BigAutoField(primary_key=True)
item_type = models.BooleanField(default=True)
item_name = models.CharField(max_length=128)
item_qty = models.PositiveIntegerField(default=0)
item_cost = models.PositiveIntegerField(default=0)
def __str__(self):
return self.item_name
class Sales(models.Model):
invoice_no = models.BigAutoField(primary_key=True)
invoice_date = models.DateField(default=date.today)
party = models.ForeignKey(Party, on_delete=models.CASCADE)
def __str__(self):
return str(self.invoice_no)
class SalesTransaction(models.Model):
sales = models.ForeignKey(Sales, on_delete=models.CASCADE)
items = models.ForeignKey(Items, on_delete=models.CASCADE)
purchase_qty = models.PositiveIntegerField(default=0)
total_cost = models.PositiveIntegerField(default=0)
def __str__(self):
return self.item_name
I can achieve this with AJAX but I don't think it is the best solution because lots of validations have to be made with hardcoding.
How can I create Django Form to save data in that multiple tables in a single Save Click?
I have been looking for a way to do the same thing recently. The solution I stumbled upon was to use two form objects under a single <form> tag. You can differentiate between the form objects by giving them prefix attributes before passing to context. For example:
def get_view(request):
....
form1 = Form1(prefix="form1")
form2 = Form2(prefix="form2")
return render(request, 'template.html', {'form1': form1, 'form2': form2})
In your template, you would call them as usual under a single form tag:
<form>
{{ form1.as_p }}
{{ form2.as_p }}
<input type='submit'>
</form>
Now in your post view, you can use the prefix to get data of each form individually:
def post_view(request):
form1 = Form1(request.POST, prefix="form1")
form2 = Form2(request.POST, prefix="form2")
....

Django temporary fields only upon creation

Consider two models:
Contract
class Contract(models.Model):
employee = models.OneToOneField(Employee, on_delete=models.CASCADE)
contract_type = models.ForeignKey(ContractType, on_delete=models.CASCADE)
start_date = models.DateField()
end_date = models.DateField()
and
Employee
class Employee(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
contract = models.OneToOneField(Contract, on_delete=models.CASCADE, null=True, blank=True)
I was wondering if there's a way to add temporary fields in a model form that are only shown upon creation in the Employee model so I can add all those fields while I create a new Employee then when saving, I first create an Employee object, then automatically generate a Contract object and edit the original Employee object and link the now generated Contract object.
I really hope this makes sense, and if it does, can someone guide me in the right direction?
Thank you, for your time reading this.
First of all, you here made two relations between Employee and Contract. Django automatically makes a relation in reverse, so you probably should remove one. Otherwise it is possible that some_contract.emplyee.contract is not the same as some_contract.
You thus for example might want to re-model this to:
class Employee(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
class Contract(models.Model):
employee = models.OneToOneField(Employee, on_delete=models.CASCADE, related_name='contract')
contract_type = models.ForeignKey(ContractType, on_delete=models.CASCADE)
start_date = models.DateField()
end_date = models.DateField()
You can just create two ModelForms:
# app/forms.py
from app.models import Employee, Contract
class EmployeeForm(ModelForm):
class Meta:
model = Employee
exclude = ['contract']
class ContractForm(ModelForm):
class Meta:
model = Contract
Then we can render the two forms:
# app/views.py
from django.shortcuts import redirect, render
from app.forms import EmployeeForm, ContractForm
def some_view(request):
if request.method == 'POST':
employee_form = EmployeeForm(request.POST)
contract_form = ContractForm(request.POST)
if employee_form.is_valid() and contract_form.is_valid():
employee = employee_form.save()
contract_form.instance.employee = employee
contract_form.save()
return redirect('some-view')
else:
employee_form = EmployeeForm()
contract_form = ContractForm()
return render(
request,
'some_template.html',
{'employee_form': employee_form, 'contract_form': contract_form}
)
in the template, we then render the two forms in the same <form> tag:
<!-- some_template.html -->
<form method="post">
{% csrf_token %}
{{ employee_form }}
{{ contract_form }}
<button type="submit">submit</button>
</form>

Cannot assign "<QuerySet [<Contact: zak>]>": "Booking.contact" must be a "Contact" instance

I have an issue, I created a form where users can make a reservation (in detail view) of a unique product. So one user can have multiples booking. The form used contain email and username. This form is in my detail.html with include variable.
{% include 'store/list.html' with list_title=name %}
So, When I run my server, go to the reservation page, put an username, email and submit, I have an error instead to redirect to an another page.
models.py:
from django.db import models
class Contact(models.Model):
email = models.EmailField(max_length=100)
name = models.CharField(max_length=200)
def __str__(self):
return self.name
class Marque(models.Model):
name = models.CharField(max_length=200, unique=True)
def __str__(self):
return self.name
class Model(models.Model): #Plusieurs models pour une marque
reference = models.IntegerField(null=True)
created_at = models.DateTimeField(auto_now_add=True)
available = models.BooleanField(default=True)
name = models.CharField(max_length=200)
picture = models.URLField()
marque = models.ForeignKey(Marque, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Booking(models.Model): #plusieurs réservation pour un contact
created_at = models.DateTimeField(auto_now_add=True)
contacted = models.BooleanField(default=False)
marque = models.OneToOneField(Marque, on_delete=models.CASCADE)
model = models.OneToOneField(Model, on_delete=models.CASCADE)
contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
def __str__(self):
return self.contact.name
views.py:
...
def detail(request, model_id):
model = get_object_or_404(Model, pk=model_id)
#marques = [marque.name for marque in model.marque.all()]
#marques_name = " ".join(marques)
if request.method == 'POST':
email = request.POST.get('email')
name = request.POST.get('name')
contact = Contact.objects.filter(email=email)
if not contact.exists():
#If a contact is not registered, create a new one
contact = Contact.objects.create(
email = email,
name = name
)
#If no album matches the id, it means the form must have been tweaked
#So returning a 404 is the best solution
model = get_object_or_404(Model, pk=model_id)
booking = Booking.objects.create(
contact = contact,
model = model
)
#Make sure no one can book the model again
model.available = False
model.save()
context = {
'model_name': model.name
}
return render(request, 'store/merci.html', context)
message = "Le model est {}. Conçu par la marque {}".format(model.name, model.marque)
context = {
"model_name" : model.name,
"model_marque" : model.marque,
"model_id": model.id,
"thumbnail" : model.picture
}
return render(request, 'store/detail.html', context)
search_form.html inside of detail.html:
<div class="container">
<div class="col-lg-12 detail-separator">
<form class="col-md-6 col-md-offset-3 text-center" action="{% url 'store:search' %}" method="get" accept-charset="utf-8">
<div class="form-group">
<label for="searchForm">Chercher un Model</label>
<input id="searchForm" class="form-control" name="query">
</div>
<span class="help-block" id="helpBlock">Trouvez le model de voiture de vos rêves !</span>
</form>
</div>
</div>
You contact query returns a queryset:
contact = Contact.objects.filter(email=email)
You then try to use contact as if it were a single Contact object:
booking = Booking.objects.create(
contact = contact,
model = model
)
This is why Django complains that it got a Queryset instead of a Contact.
You need to select one Contact even if the Queryset only contains one single object. E.g.
contacts = Contact.objects.filter(email=email)
if contacts.exists():
contact = contacts[0]
else:
#If a contact is not registered, create a new one
contact = Contact.objects.create(
email = email,
name = name
)
Or, preferably:
try:
contact = Contact.objects.get(email=email)
except DoesNotExist:
contact = Contact.objects.create(
email = email,
name = name
)

Django - how to exclude repeating objects

models.py
class Location(models.Model):
name = models.CharField(max_length=100, verbose_name=u"Локация", default=u'')
country = models.CharField(max_length=100, verbose_name=u"Страна", default=u'')
class Country(models.Model):
name = models.CharField(max_length=50, verbose_name=u"Страна")
class Photo(models.Model):
location = models.ForeignKey(Location, null=True, verbose_name=u'Фото')
photo = models.ImageField(upload_to='photos', null=True)
forms.py
class LocationForm(forms.ModelForm):
class Meta:
model = Location
fields = ['name', 'country']
photos = MultiFileField(min_num=1, max_num=10)
def save(self, commit=True):
instance = super(LocationForm, self).save(commit)
for each in self.cleaned_data['photos']:
Photo.objects.create(photo=each, location=instance)
return instance
views.py
class AddLocationPageView(CreateView):
model = Location
form_class = LocationForm
template_name = 'add_location.html'
class BrowseLocationsPageView(ListView):
model = Country
context_object_name = 'countries'
template_name = "browse_locations.html"
add_location.html
<form action="" method="POST">{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-default" type="submit">Add</button>
</form>
browse_locations.html
{% for country in countries %}
{{ country }}
{% endfor %}
I need to get in browse_locations.html the list of countries without repeating.
For exapmple, I am creating location object with country 'USA'. Then I am creating second one with country 'USA'. And in my view I can see the list where there are two 'USA', but I need only one.
Thanks!!!
If you are using postgres, then you can use the distinct queryset filter with a field name.
class BrowseLocationsPageView(ListView):
def get_queryset(self):
return self.model.objects.distinct('name')
This solves the "issue" but there is a bigger problem at hand. Wherever you are creating the countries, you are creating new countries instead of looking if there is an existing country with the same name - get_or_create may be useful here.
Location should probably have a foreign key to a country too...
You have country as a CharField in the Location Model. Hence the repitition.
Change the country field as a ForeignKey in the Location model