So i have a button on my detailView page for my model 'patient', and that takes you to a createView for my other model 'appointment'. What i want is the foreign key field of the appointment to be pre-filled depending on what detailView i come from. Here is my code so far:
urls.py:
# /patients/appointment/add
url(r'appointment/add/$', views.appointmentCreate.as_view(), name='appointment-create'),
models.py:
class patient(models.Model):
TITLE_CHOICES = (
('Mr', 'Mr'),
('Mrs', 'Mrs'),
('Ms', 'Ms'),
('Miss', 'Miss'),
)
Title = models.CharField(max_length=100, blank=True, choices=TITLE_CHOICES)
First_Name = models.CharField(max_length=250, default='')
Surname = models.CharField(max_length=250, default='')
DOB = models.DateField()
class appointment(models.Model):
Patient = models.ForeignKey(patient, on_delete=models.CASCADE)
views.py:
class appointmentCreate(LoginRequiredMixin, CreateView):
model = appointment
fields = ['Patient', 'Date', 'Time', 'Duration', 'Location', 'Clinician', 'AppointmentType']
form-template.html:
<body>
{% for field in form %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<span class="text-danger small">{{ field.errors }}</span>
</div>
<label class="control-label col-sm-2">{{ field.label_tag }}</label>
<div class="col-sm-10">{{ field }}</div>
</div>
{% endfor %}
</body>
appointment_form.html:
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-body">
<h3>Add new appointment</h3>
<form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include 'patients/form-template.html' %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
The button from the detailView of patient to create appointment:
<ul class="nav nav-pills" style="margin-bottom: 10px;">
<li role="presentation" class="active">View All</li>
<li role="presentation">Add New Appointment</li>
</ul>
For example, the url might be /appname/appointment/add/?Patient=pk , where the end part determines what the value of Patient will be. I have looked into the get_initial function but do not understand how it can help me achieve this. Any help is appreciated. I am relatively new to django so please nothing too complex.
Edit: I have added this code to my model, thanks to Dimitris Kougioumtzis:
def get_context_data(self, **kwargs):
context = super(appointmentCreate, self).get_context_data(**kwargs)
context['patient_id'] = self.request.GET.get('patient')
return context
How do i implement this code?
first you create a modelForm:
from django import forms
from your_app.models import appointment
class AppointmentForm(forms.ModelForm):
class Meta:
model = appointment
fields = ['Patient', 'Date', 'Time', 'Duration', 'Location', 'Clinician', 'AppointmentType']
Then you pass the model form in your CreateView:
class appointmentCreate(LoginRequiredMixin, CreateView):
model = appointment
form_class = AppointmentForm
def get_initial(self):
patient = self.request.GET.get('patient')
return {
'patient': patient,
}
and Your patient choicefield will be populated based on the request get parameter
Related
I am trying to create an educational website using Django, so when I am trying to render {{ profile.institution }} or {{ profile.grade }} or {{ profile.user.username }} they are not being rendered.I don't know why they aren't. Can anyone help me solve this?
My models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
institution = models.CharField(max_length = 100)
grade = models.CharField(max_length=100, choices= YEAR_IN_SCHOOL_CHOICES)
bio = models.TextField(max_length=300)
def __str__(self):
return f'{self.user.username} Profile'
My views.py:
class User_Profile(LoginRequiredMixin, ListView):
model = Profile
template_name = 'class/profile.html'
context_object_name = 'profile'
def get_queryset(self):
return Profile.objects.filter(user=self.request.user)
My html:
{% extends "class/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<br>
<div class="row d-flex justify-content-center">
<h1 style="color: #f5a425">Hello {{ user.username }}</h1>
</div>
<div class="container mt-5">
<div class="row d-flex justify-content-center">
<div class="col-md-7">
<div class="card p-3 py-4">
<div class="text-center">
<i class='fas fa-user-alt' style='font-size:36px'></i>
<!-- <img src="" width="100" class="rounded-circle"> -->
</div>
<div class="text-center mt-3">
<span class="bg-secondary p-1 px-4 rounded text-white">Pro</span>
<h5 class="mt-2 mb-0">{{ profile.user.username }}</h5>
<span>{{ profile.institution }}</span>
<span>{{ profile.grade }} Grade</span>
<div class="px-4 mt-1">
<p class="fonts">{{ profile.bio }}</p>
</div>
<div class="buttons">
<button class="btn btn-outline-primary px-4">Message</button>
<button class="btn btn-primary px-4 ms-3">Contact</button>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
what part of the code should I change to make this work ?
ListView it is about many objects ant iteration through the object_list. In this case the answer of #PouyaEsmaeili is correct.
But. The mistake is - you have a wrong view. DetailView is the right choose.
This returns always one object or nothing.
Profile.objects.filter(user=self.request.user)
In your case:
class User_Profile(LoginRequiredMixin, DetailView):
model = Profile
template_name = 'class/profile.html'
context_object_name = 'profile'
def get_object(self):
return get_object_or_404(self.model, user=self.request.user)
If you set name for template profile_detail.html, you don't need template_name attribute. It should be find automatically.
If you don't change the model_name in Profile._meta - , you don't need context_object_name attribute. It should be defined automatically.
Please, don't forget about Django-views naming best practices.
Last version of your view can be:
class ProfileDetailView(LoginRequiredMixin, DetailView):
model = Profile
def get_object(self):
return get_object_or_404(self.model, user=self.request.user)
I'm trying to update a user profile using two forms the problem is that when I click to update I get the following error:
“<ul class="errorlist">
<li>username<ul class="errorlist"><li>This field is required.</li>
</ul>
”
My model module is the following:
# user.models
from django.contrib.auth.models import AbstractUser
from django.db import models
from model_utils.models import TimeStampedModel
from localflavor.br.models import BRPostalCodeField, BRStateField, BRCNPJField, BRCPFField
class User(AbstractUser):
class Roles(models.IntegerChoices):
SUPER = 0
COMPANY = 1
UNITY = 2
STAFF = 3
picture = models.ImageField(blank=True, null=True)
role = models.IntegerField(choices=Roles.choices, default=Roles.STAFF)
class Staff(TimeStampedModel):
user: User = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
unity = models.ForeignKey(Unity, related_name="staff", on_delete=models.CASCADE)
cpf = BRCPFField("CPF")
class Meta:
verbose_name: str = 'Staff'
verbose_name_plural: str = 'Staff'
ordering = ("-created",)
def __str__(self):
if f"{self.user.first_name} {self.user.last_name}".strip():
return f"{self.user.first_name} {self.user.last_name}"
return str(self.user.username)
And my user forms looks like:
#user.forms
class UserModelForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email', 'is_active']
class StaffModelForm(forms.ModelForm):
class Meta:
model = Staff
fields = ['cpf', 'unity']
widget = {
'cpf': forms.TextInput(attrs={'class': "form-control", 'placeholder': 'Primeiro Nome', }),
'unity': forms.EmailInput(attrs={'class': "form-control", 'placeholder': 'meu#email.com', }),
}
with the following view:
#views
…
def update_staff(request: HttpRequest, pk: int) -> HttpResponse:
instance: Staff = get_object_or_404(Staff, pk=pk) # get staff instance
template_name = 'pages/staff_update_form.html' # use this template
if request.method == "POST":
profile_form = user_forms.StaffModelForm(request.POST, instance=instance)
user_form = user_forms.UserModelForm(request.POST, request.FILES, instance=instance.user)
print(user_form.is_valid())
print(user_form.errors)
print(profile_form.is_valid())
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, 'Your profile is updated successfully')
return redirect(to='pages:dashboard')
context = dict(profile_form=user_forms.StaffModelForm(instance=instance),
user_form=user_forms.UserModelForm(instance=instance.user))
return render(request, template_name=template_name, context=context)
Print output:
False
<ul class="errorlist"><li>username<ul class="errorlist"><li>This field is required.</li></ul
></li></ul>
True
and HTML:
{% load crispy_forms_tags %}
{% if user_form.errors %}
<div class="alert alert-danger alert-dismissible" role="alert">
<div id="form_errors">
{% for key, value in user_form.errors.items %}
<strong>{{ value }}</strong>
{% endfor %}
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
<div class="py-5 text-center">
<span class="material-icons" style="height: 48px; width: auto; font-size: 48px;">people_alt</span>
<h1 class="h3 mb-3 fw-normal">Atualize aqui os dados do usuário!</h1>
</div>
<form class="form-signin" method="POST" enctype="multipart/form-data">
<div class="form-group">
<div class="row g-8 my-auto mx-auto" style="padding-left: 12%; padding-right: 12%;">
<div class="col-md-8 col-lg-12">
{% crispy profile_form %}
</div>
</div>
<div class="row g-8 my-auto mx-auto" style="padding-left: 12%; padding-right: 12%;">
<div class="col-md-8 col-lg-12">
{% crispy user_form %}
</div>
</div>
<div class="col-md-12 col-lg-12">
<br>
<div class="modal-footer">
Cancel
<button class="btn btn-primary mb-2" type="submit">Update</button>
</div>
</div>
</div>
</form>
<div class="py-5 text-center">
<p class="mt-5 mb-3 text-muted">© 2022-2023</p>
</div>
So I have no idea what the source of this problem is. Everything seems fine to me, can anyone help me?
I am trying to make a page in django where users can look at their profiles and edit and save the changes, but everytime i click on the save button, nothing happens and when I refresh the page, the information doesn't get updated. What am I doing wrong?
This is my models.py:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User,null= True ,on_delete= models.CASCADE)
profile_pic = models.ImageField(null = True, blank= True)
first = models.CharField(max_length=500, null=True)
last = models.CharField(max_length=500, null=True)
email = models.CharField(max_length=500, null=True)
mobile_number = models.IntegerField(null=True)
location = models.CharField(max_length= 500, null= True)
postal = models.IntegerField(null=True)
def __str__(self):
return self.first
This is my forms.py:
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = '__all__'
exclude = ['user']
widgets = {
'profile_pic': forms.FileInput()
}
This is my views.py:
#login_required(login_url='Login')
def Profile(request):
profile = request.user.profile
form = ProfileForm(instance=profile)
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILE, instance=profile)
if form.is_valid():
form.save()
return HttpResponseRedirect(reversed('Profile'))
context = {'form': form}
return render(request, 'profile.html', context)
This is my template:
<div class="col-lg middle middle-profile-con">
<div class="img-cir profile-img">
<img src="{{request.user.profile.profile_pic.url}}" alt="" width="100px" height="100px" class="pro-img">
</div>
<form method='POST' action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="">
<p class="my-name-pro">{{request.user.profile.first}}
<p>
<p class="my-email-id-pro">{{request.user.profile.email}} <br> {{form.profile_pic}}</p>
</div>
<div class="">
<div class="pro-fn-div">
<label class="pro-fn-label">First name</label>
<div class="pro-fn-input"> {{form.first}} </div>
</div>
<div class="pro-ln-div">
<label class="pro-fn-label">Last name</label>
<div class="pro-fn-input"> {{form.last}} </div>
</div>
<div class="pro-email-div">
<label class="pro-fn-label">Email ID</label>
<div class="pro-fn-input"> {{form.email}} </div>
</div>
<div class="pro-pn-div">
<label class="pro-fn-label">Phone Number</label>
<div class="pro-fn-input"> {{form.mobile_number}} </div>
</div>
<div class="pro-lo-div">
<label class="pro-fn-label">Location</label>
<div class="pro-fn-input"> {{form.location}} </div>
</div>
<div class="pro-pc-div">
<label class="pro-fn-label">Postal Code</label>
<div class="pro-fn-input"> {{form.postal}} </div>
</div>
<button type="button" name="Update Information" class="btn btn-dark btn-sm pro-btn-save">Save Changes</button>
</form>
</div>
I don't understand where I'm going wrong. Do I need to add something in the template? Maybe in the save button or something?
You forgot to register your url so for example :
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('profile/', views.profile, name="profile"),
]
In your template, edit your form
<form method='POST' action="{% url 'profile' %}" enctype="multipart/form-data">
Note that variable in Python are lowercase, following the convention is best
I am trying to implement dynamic tabs in my project that gives multiple tabs based on the values stored in the database.
In my case, I have two values stored in database so it's displaying just two, If I will increase more, it will show accordingly.
Category.objects.filter(category='MEDICINES')
Out[14]: <QuerySet [<Category: FRUITS>, <Category: GRAINS>]>
Here is my models.py file,
from django.db import models
from django.contrib.auth.models import User
STATUS = ((0, "Draft"), (1, "Publish"))
class Category(models.Model):
category_names = (
('DISEASES','DISEASES'),
('MEDICINES','MEDICINES'),
('ENCYCLOPEDIA','ENCYCLOPEDIA'),
)
category = models.CharField(max_length=100, choices=category_names)
sub_category = models.CharField(max_length=100, unique=True)
def __str__(self):
return self.sub_category
class Medicine(models.Model):
title = models.CharField(max_length=200, unique=True)
display_name = models.CharField(max_length=17, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='medicine_posts')
category = models.ForeignKey(Category, on_delete=models.CASCADE)
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ["-created_on"]
def __str__(self):
return self.title
def get_absolute_url(self):
from django.urls import reverse
return reverse("medicine_detail", kwargs={"slug": str(self.slug)})
Here it my views.py file,
from django.views import generic
from .models import Medicine, Category
from django.shortcuts import render, get_object_or_404
class MedicineList(generic.ListView):
queryset = {'medicine' : Medicine.objects.filter(status=1).order_by("-created_on"),
'category' : Category.objects.all()
}
#queryset = Medicine.objects.filter(status=1).order_by("-created_on")
print(queryset)
template_name = "medicine.html"
context_object_name = 'element'
#paginate_by = 10
Here is my medicine.html file,
<div class="container">
<div class="row">
<div class="col-md-8 mt-3 left">
<nav>
<div class="nav nav-tabs nav-fill" id="nav-tab" role="tablist">
{% for item in element.category %}
<a class="nav-item nav-link active" id="{{ item.id }}" data-toggle="tab" href="#{{ item }}" role="tab" aria-controls="nav-home" aria-selected="true">{{ item }}</a>
{% endfor %}
</div>
</nav>
{% for item in element.category %}
<div class="tab-content py-3 px-3 px-sm-0" id="nav-tabContent">
<div class="tab-pane fade show active" id="{{ item }}" role="tabpanel" aria-labelledby="{{ item.id}}">
<table class="col-md-8 mt-3 left">
{% for post in element.medicine %}
{% cycle 'row' '' as row silent %}
{% if row %}<tr>{% endif %}
<td style="padding: 10px;">
<div class="card mb-4">
<div class="card-body">
<h6 class="card-title text-center"> {{ post.display_name }}</h6>
</div>
</div>
</td>
{% if not row %}</tr>{% endif %}
{% endfor %}
</table>
</div>
</div>
{% endfor %}
</div>
{% block sidebar %}
{% include 'sidebar.html' %}
{% endblock sidebar %}
</div>
</div>
Please help me out with this code, it;s not working.
Your queryset should not be a dictionary, Django expects a queryset instance here.
Try:
class MedicineList(generic.ListView):
queryset = Category.objects.all()
# or: model = Category
template_name = "medicine.html"
context_object_name = 'element'
I've been trying to display the exact values of model with ManyToMany relation but I just couldn't, all what I've achevied is receiving QuerySet
<QuerySet [<Stack: PHP>, <Stack: js>]>
by adding to template tags
{{ brand.technologies.all }}
But I would like to receive and display 2 fields, name and icon. I've tried with some loops like
{% for brand in brands %}
{% for technologies in brand.technologies.all %} {{ technologies.name }} {{ technologies.icon }} {% endfor %}
{% endfor %}
but it doesn't give any results. There is not problem with syntax because page is displaying and looks like this
image
models.py
STACK = (
('PHP', 'PHP'),
('js', 'JavaScript'),
...
)
STACK_ICONS = (
('/static/icons/stack/php.png', 'PHP'),
('/static/icons/stack/javascript.png', 'JavaScript'),
...
)
class Company(models.Model):
name = models.CharField(max_length=100, blank=False)
students = models.CharField(max_length=3, choices=STUDENTS)
type = models.CharField(max_length=15, choices=TYPES)
workers = models.PositiveIntegerField(validators=[MinValueValidator(1)])
city = models.CharField(max_length=15,choices=CITIES)
company_about = models.TextField(max_length=500, blank=False)
slug = models.SlugField(unique=True)
icon = models.ImageField(blank=True, null=True)
image = models.ImageField(blank=True, null=True)
logo = models.ImageField(blank=True, null=True)
technologies = models.ManyToManyField('Stack')
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Company, self).save(*args, **kwargs)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.name
# object stack relation manytomany with Company
class Stack(models.Model):
name = models.CharField(max_length=30, choices=STACK)
icon = models.CharField(max_length=80, choices=STACK_ICONS)
def __str__(self):
return self.name
views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
...
def comp_list(request):
f = CompanyFilter(request.GET, queryset=Company.objects.all())
return render(request, 'company/comp_list.html', {'filter': f})
def companies(request):
company = get_object_or_404(Company)
return render(request, 'company/comp_list.html', {'company': company})
def home(request):
return render(request, 'company/home.html')
def brands(request, slug):
brand = get_object_or_404(Company, slug=slug)
return render(request, 'company/comp_view.html', {'brand': brand})
def stacks(request):
stack = get_object_or_404(Stack)
return render(request, 'company/comp_view.html', {'stack': stack})
comp_view.html
{% extends 'company/base.html' %}
{% block content %}
<div class="row company-details">
<div class="col col-md-2"></div>
<div class="col col-md-8">
<input class="btn btn-success" type="button" value="Go Back" onclick="history.back(-1)" />
<div class="col col-md-12 company-bg" style="background-image: url('{{ brand.image.url }}'); background-repeat: no-repeat, repeat;">
</div>
<div class="bottom-overlay"></div>
<div class="company-description">
<div class="heading">
<div class="title">About us</div>
<div class="social-media">
Facebook
</div>
</div>
<div class="company-about">
{{ brand.company_about }}
</div>
</div>
<div class="company-stats">
<div class="company-logo-container">
<img class="company-logo" src="{{ brand.logo.url }}">
</div>
<div class="company-attributes">
<div class="field-group">
<div class="field">Type</div>
<div class="value">{{ brand.type }}</div>
</div>
<div class="field-group">
<div class="field">Company size</div>
<div class="value">{{ brand.workers }}+</div>
</div>
<div class="field-group">
<div class="field">Headquarters</div>
<div class="value">{{ brand.city }}</div>
</div>
<div class="field-group">
<div class="field">Open for students</div>
<div class="value">{{ brand.students }}</div>
</div>
</div>
<div class="technologies-section">
<p class="tech-heading">Technologies</p>
<div class="technologies-wrapper">
{{ brand.technologies.all }}
{% for brand in brands %}
{% for technologies in brand.technologies.all %} {{ technologies.name }} {% endfor %}
{% endfor %}
</div>
</div>
</div>
<div class="col col-md-2"></div>
</div>
{% endblock %}
I don't understand why you've suddenly added an outer loop through brands. You don't have anything called brands, and you're successfully accessing all the other data via brand. Just continue to do so, and drop the outer loop.
<div class="technologies-wrapper">
{% for technologies in brand.technologies.all %} {{ technologies.name }} {% endfor %}
</div>