How to join different models with primary key in Django? - django

I am very new on Django. I wanna make patient storage system but i'm stuck.
These things must be in project.
1-) In my project i want to add hundreds of patients and also some new patients can add their own infos via register.
2-) Every patients will answer more then 300 questions, so i wanna split the model for good user experience.
Here is the my problem.
I split the main models, and then i add some basic information from hastaekle.html and then when i looked the admin panel. I see this selection page on the image at below. How can it be automatically.
Here is my models.py
from django.db import models
from django.shortcuts import render
from django.urls import reverse
# Create your models here.
class HastaProfil(models.Model):
#id = models.IntegerField(primary_key=True)
hasta_ad = models.CharField(max_length=155)
hasta_soyad = models.CharField(max_length=155)
hasta_dogum_yeri = models.CharField(max_length=155)
def __str__(self):
return self.hasta_ad + ' ' + self.hasta_soyad
def get_absolute_url(self):
return reverse('hasta-aliskanlik')
class HastaAliskanlik(models.Model):
#id = models.IntegerField(primary_key=True)
sigara = models.CharField(max_length=155)
alkol = models.CharField(max_length=155)
uyusturucu = models.CharField(max_length=155)
def __str__(self):
return self.sigara
def get_absolute_url(self):
return reverse('hasta-listele')
class Hasta(models.Model):
#id = models.IntegerField(primary_key=True)
hastaprofil = models.ForeignKey(HastaProfil, on_delete=models.CASCADE, null=True)
hastaaliskanlik = models.ForeignKey(HastaAliskanlik, on_delete=models.CASCADE, null=True)
forms.py
from .models import HastaAliskanlik, HastaProfil, Hasta
from django import forms
class HastaProfilForm(forms.ModelForm):
class Meta:
model = HastaProfil
fields = '__all__'
widgets = {
'hasta_ad' : forms.TextInput(attrs={'class': 'form-control'} ),
'hasta_soyad' : forms.TextInput(attrs={'class': 'form-control'}),
'hasta_dogum_yeri' : forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Tıklayarak Seçiniz'}),
}
class HastaAliskanlikForm(forms.ModelForm):
class Meta:
model = HastaAliskanlik
fields = '__all__'
widgets = {
'sigara' : forms.TextInput(attrs={'class': 'form-control'} ),
'alkol' : forms.TextInput(attrs={'class': 'form-control'}),
'uyusturucu' : forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Tıklayarak Seçiniz'}),
}
class HastaForm(forms.ModelForm):
class Meta:
model = Hasta
fields = '__all__'
widgets = {
'hastaprofil' : forms.TextInput(attrs={'class': 'form-control'} ),
'hastaaliskanlik' : forms.TextInput(attrs={'class': 'form-control'}),
#'uyusturucu' : forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Tıklayarak Seçiniz'}),
}
views.py
from django.http import HttpResponse
from django.shortcuts import render
from django.views.generic import CreateView
from .forms import HastaProfilForm, HastaAliskanlikForm, HastaForm
from .models import HastaProfil, HastaAliskanlik, Hasta
# Create your views here.
class HastaProfil(CreateView):
model = HastaProfil
form_class = HastaProfilForm
template_name = 'hastaekle.html'
class HastaAliskanlik(CreateView):
model = HastaAliskanlik
form_class = HastaAliskanlikForm
template_name = 'hasta_aliskanlik.html'
def HastaListele(request):
tum_hasta = Hasta.objects.all()
return render(request, 'hasta_listele.html', {'tum_hasta': tum_hasta})
def Home(request):
return render(request, 'home.html')
hastaekle.html
<html>
<head>
<title>Hasta Ekle </title>
</head>
<body>
Anasayfa <br>
Hasta Listele
<h1>Hasta Ekle </h1>
<form action="" method="POST">
{% csrf_token %}
<h3>Hasta Profil Ekle:</h3>
Hasta Ad: <input type="text" name="hasta_ad"/><br/>
Hasta Soyad: <input type="text" name="hasta_soyad"/><br/>
Hasta Doğum Yeri: <br/>
<textarea cols="35" rows="8" name="hasta_dogum_yeri">
</textarea><br/>
<input type="submit" value="Post"/>
</form>
</body>
</html>
hasta_aliskanlik.html
<html>
<head>
<title>Alışkanlıklarınız </title>
</head>
<body>
Anasayfa <br>
Hasta Listele
<h1>Hasta Ekle </h1>
<form action="" method="POST">
{% csrf_token %}
<h3>Alışkanlıklarınız:</h3>
Sigara: <input type="text" name="sigara"/><br/>
Alkol: <input type="text" name="alkol"/><br/>
Uyuşturucu: <br/>
<textarea cols="35" rows="8" name="uyusturucu">
</textarea><br/>
<input type="submit" value="Post"/>
</form>
</body>
</html>
hasta_listele.html
<h1>Hastalar</h1>
Anasayfa <br>
Hasta Ekle
<ul>
{% for post in tum_hasta %}
<li>{{ post.hastaprofil.hasta_ad }} {{ post.hastaprofil.hasta_soyad }}
{% endfor %}
</ul>

I think you can not do it in this way because the problem what if multi users post data in same time in HastaProfil and HastaAliskanlik and for example one user post on HastaProfil and another one on HastaAliskanlik, how you will now this information for any user?
you should add on those model special field like user or link between those model, after that you can use access data in easy way

You need to use OneToOneField
class HastaAliskanlik(models.Model):
hasta_profil = models.OneToOneField(
HastaProfil,
on_delete=models.CASCADE,
primary_key=True,
)
sigara = models.CharField(max_length=155)
...

Related

admin is not able to approve post for the required like field django

In my django project, users can create posts. but the admin has to approve the post first. Then the users can see the posts created by them in their timeline. The users can like or unlike post from the post-detail page. However, when the admin logs in from the django admin panel to approve post and click the save button, it shows that the 'like' field is required. How can I solve this problem so that the admin can approve the post?
blog/models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth import get_user_model
from django.urls import reverse
from ckeditor.fields import RichTextField # first I installed ckeditor by this command: pip install django-ckeditor
# Create your models here.
class Category(models.Model):
cid = models.AutoField(primary_key=True)
category_name = models.CharField(max_length=100)
def __str__(self):
return self.category_name
class Post(models.Model):
aid = models.AutoField(primary_key=True)
image = models.ImageField(default='blog-default.png', upload_to='images/')
title = models.CharField(max_length=200)
# content = models.TextField()
content = RichTextField()
created = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
cid = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name='specialization')
approved = models.BooleanField('Approved', default=False)
like = models.ManyToManyField(get_user_model(), related_name='likes')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk':self.pk})
#property
def total_likes(self):
return self.like.count()
users/models.py
from django.db import models
from blog.models import Category
from django.contrib.auth.models import AbstractUser
# Create your models here.
class CustomUser(AbstractUser):
cid = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True, null=True)
profile_pic = models.ImageField(default='default_person.jpg', upload_to='profile_pics')
blog/forms.py
from django import forms
from .models import Post, Comment
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content', 'image', 'cid']
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'content': forms.Textarea(attrs={'class': 'form-control'}),
'image': forms.FileInput(attrs={'class': 'form-control'}),
'cid': forms.Select(attrs={'class': 'form-control'}),
}
class EditForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content', 'image', 'cid']
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'content': forms.Textarea(attrs={'class': 'form-control'}),
'cid': forms.Select(attrs={'class': 'form-control'}),
}
users/forms.py
from django import forms
from django.contrib.auth import get_user_model # I changed the default User model. So I need to change the way I access it The right way to use it is get_user_model()
from django.contrib.auth.forms import UserCreationForm # it is used to create a new user
from blog.models import Category
User = get_user_model()
class UserRegisterForm(UserCreationForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['specialization'].required = True
email = forms.EmailField()
categories = Category.objects.all()
specialization = forms.ModelChoiceField(queryset=categories)
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2', 'specialization']
blog/post-detail.html
{% extends 'users/base.html' %}
{% block content %}
<div class="card mb-3">
<img class="card-img-top" src="{{ object.image.url }}" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{ object.title }}</h5>
<p class="card-text">{{ object.content|safe }}</p>
<p class="card-text"> <b> Specialization: </b> {{ object.cid }} </p>
{% if object.author == user %}
<div>
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-update' object.aid %}">Edit</a>
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-delete' object.aid %}">Delete</a>
</div>
{% endif %}
<hr>
<form action="{% url 'post-like' object.pk %}" method="POST">
{% csrf_token %}
{% if post_is_liked %}
<button type="submit" name="post_id" value="{{object.aid}}" class="btn btn-danger btn-sm">Unlike</button>
{% else %}
<button type="submit" name="post_id" value="{{object.aid}}" class="btn btn-info btn-sm">Like</button>
{% endif %}
- {{ post.like.count }} Likes
</form>
</div>
<div class="card-footer text-secondary">
<a class="mr-2" href="{% url 'other-people-profile' object.author.username %}">{{ object.author }}</a>||
{{ object.created|date:"F d, Y" }}
</div>
</div>
{% endblock content %}
The field like is not mark as optional.
like = models.ManyToManyField(get_user_model(), related_name='likes', blank=True)

Date field dont autofill value Django

My browser (chrome and firefox) doesn`t autofill my Datefield, but in safari working example
I inspected my html
HTML field have value
my view.py
def get(self, request, slug):
order = get_object_or_404(Order, order_number=slug)
form = DirectorForm(instance=order)
return render(request, 'edit_order.html', context={'form': form})
my forms.py
widgets = {'order_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'})}
Well you don't need datefield widget for this you have to import datetime module in your models.py and use it to fill date or time
To be more specific here is my github link to a simple django project i did when i first started : https://github.com/AYUSHJD098/Django-Notes
and the site is : http://www.djangonotes.tk
you just need to add " date = models.DateField(auto_now_add=True, null=True) " in your models.py
like this
models.py
from django.db import models
from django.contrib.auth.models import User
class note(models.Model):
title = models.CharField(max_length=512, null=True)
note = models.TextField(null=True)
date = models.DateField(auto_now_add=True, null=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
The value will get added automatically when you save data to your database
here is a example:
home.html
{% if notes %}
{% for note1 in notes %}
<div class="container">
<div class="row justify-content-center">
<div class="col">
<div class="jumbotron">
<h1 class="display-4">{{note1.title}}</h1>
<p class="lead">{{ note1.date }}</p>
<hr class="my-4">
<p class="lead">{{ note1.note }}</p>
<a class="btn btn-outline-info" href="{% url 'view_note' pk=note1.id %}">Open</a>
</div>
</div>
</div>
</div>
forms.py
from django.forms import ModelForm, TextInput, Textarea
from .models import *
class noteForm(ModelForm):
class Meta:
model = note
fields = ('title', 'note')
widgets = {
'title': TextInput(attrs={'class': 'form-control', 'placeholder':'title'}),
'note': Textarea(attrs={'class': 'form-control', 'rows':'16','placeholder':'note'})
}
P.s sorry if i sound like a complete idoit i am very bad at explainging and i am kinda new to programming
Thanks,
ayush :)

Django: How to display foreign key objects of a model in manual form field as choices

So I have 2 models called Billing and Organization as shown below. Billing in the admin site works as expected i.e the organization field shows all organizations listed and gives me an option to pick one. If I implement a model form for Billing it doesn't display all organizations that I can pick from. How to Implement this? I have shared forms.py, views.py code below.
models.py
class Organization(models.Model):
name = models.CharField(max_length=255, unique=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return str(self.name)
class Billing(models.Model):
invoice_name = models.CharField(max_length=50)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
product = models.ManyToManyField(Product)
def __str__(self):
return str(self.invoice_name)
views.py
class BillingCreateView(AdminStaffRequiredMixin, SuccessMessageMixin, CreateView):
model = Billing
form_class = forms.BillingCreateForm
template_name = 'dashboard/billing_new.html'
success_message = 'Invoice has been created successfully!'
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
dashboard/billing_new.html
<!-- start form -->
<div class="col-lg-12">
<form method="post" action="{% url 'product_create' %}" class="mailform off2" enctype="multipart/form-data">
<div class="row">
{% csrf_token %}
<div class="col-md-6 offset-md-3">
{{ form.invoice_name }}
</div>
<div class="col-md-6 offset-md-3">
{{ form.organization }}
</div>
<div class="col-md-6 offset-md-3">
{{ form.product }}
</div>
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<div class="mfControls col-md-12 offset-md-3 text-left mt-2">
<button type="submit" class="btn white">{% trans "CREATE" %}</button>
</div>
</div>
</form>
</div>
<!-- end form -->
forms.py
class BillingCreateForm(forms.ModelForm):
class Meta:
model = models.Billing
fields = ['invoice_name', 'organization', 'product']
widgets = {
'invoice_name': forms.TextInput(attrs={'type': 'text', 'name': 'name', 'placeholder': 'Invoice Name:'}),
'organization': forms.TextInput(attrs={'type': 'text', 'name': 'name', 'placeholder': 'Company:'}),
'items': forms.TextInput(attrs={'type': 'text', 'name': 'name', 'placeholder': 'Items:'}),
}
I fixed this problem by using forms.select widget in forms.py as follows:-
class BillingCreateForm(forms.ModelForm):
class Meta:
model = models.Billing
fields = ['invoice_name', 'organization', 'product']
widgets = {
'invoice_name': forms.TextInput(attrs={'type': 'text', 'name': 'name', 'placeholder': 'Invoice Name:'}),
'organization': forms.Select(attrs={'type': 'text', 'name': 'name', 'placeholder': 'Company:'}),
'items': forms.TextInput(attrs={'type': 'text', 'name': 'name', 'placeholder': 'Items:'}),
}

DateInput - Enter a valid date

I have a form field that I want to have as a calendar widget that defaults to the current date. I had it so it was showing the date in d/m/y format but when I'd submit it would say Enter a valid date
forms.py
class CreateBlogPostForm(forms.ModelForm):
published = forms.DateField()
class Meta:
model = BlogPost
fields = ('title', 'published','featured_image', 'post',)
widgets = {
'title': forms.TextInput(attrs={'class': 'blog-title-field', 'placeholder': 'Title'}),
'published': forms.DateInput(format=('%d-%m-%Y'), attrs={"type": 'date'}),
'post': forms.TextInput(attrs={'class': 'blog-post-field', 'placeholder': 'Write something..'}),
}
models.py
class BlogPost(models.Model):
title = models.CharField(max_length=100)
published = models.DateField()
featured_image = models.ImageField(upload_to='blog/%Y/%m/%d')
post = models.TextField()
slug = AutoSlugField(null=True, default=None,
unique=True, populate_from='title')
class Meta:
verbose_name_plural = "Blog"
def __str__(self):
return self.title
create-blog.html
{% extends 'base.html' %}
{% block content %}
<div class="container text-center">
<form enctype="multipart/form-data" method="POST">
{% csrf_token %}
{{form.title}}
{{form.post}}
{{form.featured_image}}
{{form.published}}
{{form.errors}}
<button type="submit" class="btn btn-primary"><i class="fa fa-plus" aria-hidden="true"></i> Submit</button>
</form>
</div>
{% endblock content %}
If you see carefully, your DateInput format is as format=('%d-%m-%Y') while your question states that your format for date is in d/m/y. Try with the hyphen instead of the slash, or vice versa and you should be fine.

django form rendering out of order

I'm learning how to use ModelForms and I've successfully gotten the form to render, but the fields aren't showing up in the order that I'd like them to. I tried changing the order in forms.py and that had no effect. How can I go about changing the order; for instance, putting title at the top instead of the bottom and making the picture field second to last instead of second?
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=150)
price = models.CharField(max_length=100)
body = models.TextField()
pub_date = models.DateTimeField(null=True)
author = models.ForeignKey(User, null=True)
category = models.CharField(max_length=150, null=True)
picture = models.ImageField(upload_to='ad_pictures', default='')
def __str__(self):
return self.title
forms.py
from django import forms
from .models import Post
from django.contrib.auth.models import User
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = {
'title',
'body',
'category',
'price',
'picture',
}
views.py
def create(request):
form = PostForm(request.POST or None, request.FILES or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return render(request, 'classifieds/latest-ads.html')
else:
form = PostForm()
args = {'form': form}
return render(request, 'classifieds/create-post.html', args)
create.html
{% extends 'base.html' %}
{% block head %}
<!-- {% load static %}
<link rel="stylesheet" href="{% static 'accounts/login.css' %}" type="text/css"> -->
<title>Create Post</title>
{% endblock %}
{% block body %}
<div class="container"><br>
<form method="POST" action='' enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" value="submit">Submit</button>
</form>
</div>
{% endblock %}
I'd like to point out that in this video the uploader is able to manipulate the order and have the changed render in the template but I cannot.
Any insight is greatly appreciated.
No need for field_order = ['price', 'title', 'body', 'category', 'picture']
Just replace {} with () for fields
so you should have:
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = (
'title',
'body',
'category',
'price',
'picture',
)