I created models for companies in my new application in django and have also created the instance for it to show detail page for each company. But when a company is clicked, it shows the id of the company instead of the name in URL like this: http://127.0.0.1:8000/companies/2/
is there a way I can make it return the company name instead like this: http://127.0.0.1:8000/companies/stackoverflow/
this is the code for my model and am using function based views for this:
class Company(models.Model):
Online_Merchant = 'merch'
Education = 'edu'
Transportation = 'trans'
Hospitalism = 'hosp'
Healthcare = 'health'
Construction = 'const'
Blog = 'blog'
Finance = 'fin'
Media = 'media'
Government_Agency = 'agency'
Other = 'other'
Manufacturing = 'manufacturing'
sector = [
(Online_Merchant, 'Online Merchant'),
(Education, 'Education'),
(Transportation, 'Transportation'),
(Hospitalism, 'Hospitalism'),
(Healthcare, 'Healthcare'),
(Construction, 'Construction'),
(Blog, 'Blog'),
(Finance, 'Finance'),
(Media, 'Media'),
(Manufacturing, 'Manufacturing'),
(Government_Agency, 'Government Agency'),
(Other, 'Other')
]
Free = 'Free'
Premium = 'Premium'
package = [
(Free, 'Free'),
(Premium, 'Premium')
]
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='Company User')
company_sector = models.CharField(max_length=30, choices=sector, default=Online_Merchant, verbose_name='Sector')
company_name = models.CharField(max_length=100)
company_description = models.TextField()
company_logo = models.ImageField(upload_to='company_logos', blank=True, null=True)
company_address = models.TextField(max_length=2000)
rating_array = ArrayField(models.IntegerField(), size=0, default=list)
average_rating = Int_max.IntegerRangeField(default=0, verbose_name='Avg', min_value=1, max_value=5)
total_views = models.IntegerField(default=0)
company_website = models.CharField(max_length=500, blank=True, null=True)
company_email = models.EmailField(max_length=500, blank=True, null=True)
company_phone = models.CharField(max_length=500)
package_chosen = models.CharField(max_length=8, choices=package, default=Free)
company_views = models.IntegerField(default=0)
featured = models.BooleanField(default=False)
advert = models.BooleanField(default=False)
premium = models.BooleanField(default=False)
def get_absolute_url(self):
"""Returns the url to access a particular instance of the model."""
return reverse("detail", kwargs={ "id": self.id })
def __str__(self):
return self.company_name
def __repr__(self):
return self.company_name
SlugField is designed for this. the django admin will help populate it as well.
models.py
class Company(models.Model):
...other model fields...
company_slug = models.SlugField(max_length=255, allow_unicode=True)
def get_absolute_url(self):
"""Returns the url to access a particular instance of the model."""
return reverse("detail", kwargs={ "slug": self.company_slug })
admin.py
class CompanyAdmin(admin.ModelAdmin):
prepopulated_fields = {"company_slug": ("company_name",)}
...admin code...
and to use it in a query:
company = Company.objects.get(company_slug=kwargs.get('company_slug')
urls.py
urlpatterns = [ path('<slug:company_slug>/', views.dynamic_url, name='detail'), ]
Related
I'm learning django and I'm trying to display all items from a specific user which is the 2003-111
itemid sy sem resolve_by
book 2021-2022 2 2003-111
table 2021-2022 1 2012-455
here's my models.py I'm using customuser to use email as authentication instead of username and replace my id with userid(character)
class ClearanceCustomuser(models.Model):
password = models.CharField(max_length=128)
last_login = models.DateTimeField(blank=True, null=True)
is_superuser = models.BooleanField()
userid = models.CharField(primary_key=True, max_length=9)
email = models.CharField(unique=True, max_length=254)
is_staff = models.BooleanField()
is_active = models.BooleanField()
date_joined = models.DateTimeField()
class Meta:
managed = False
db_table = 'clearance_customuser'
class ClearanceItem(models.Model):
itemid = models.CharField(primary_key=True, max_length=20)
sem = models.CharField(max_length=1, blank=True, null=True)
sy = models.CharField(max_length=9, blank=True, null=True)
resolve_by = models.ForeignKey('ClearanceCustomuser', models.DO_NOTHING,
db_column='resolve_by', blank=True, null=True)
class Meta:
managed = False
db_table = 'clearance_item'
for now this is my views.py
def index(request):
context = {}
context['items'] = ClearanceItem.objects.all()
return render(request, 'clearance/index.html', context)
which is displaying all items. I was thinking of something like this
select b.cl_itemid,b.sem,b.sy,b.resolve_by
from curriculum.clearance_customuser a
INNER JOIN curriculum.clearance_item b ON a.userid = b.resolve_by
where resolve_by = '2003-221'
if 2003-111 is userid field of ClearanceCustomuser than you go like:
def index(request):
context = {}
context['items'] = ClearanceItem.objects.filter(resolve_by__userid='2003-111')
return render(request, 'clearance/index.html', context)
if you want to pass userid as parameter in yours urls.py edit path to index:
path('<str:userid>/', views.index, name='index')
and in view:
def index(request, userid):
context = {}
context['items'] = ClearanceItem.objects.filter(resolve_by__userid=userid)
return render(request, 'clearance/index.html', context)
I have models like this :
class Region(models.Model):
region_parent = models.ForeignKey(
"self", blank=True, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
title = models.CharField(max_length=255)
description = RichTextField()
description_on_list = RichTextField(blank=True)
thumbnail = models.ImageField(
upload_to="thumbnail-region", blank=True, max_length=255)
sidebar = RichTextField(blank=True)
ad_manager = models.TextField(blank=True)
meta_keywords = models.TextField(blank=True)
logo_on_navbar = models.ImageField(
upload_to="logo-on-navbar/", blank=True, max_length=255)
display_on_navbar = models.BooleanField(default=True)
slug = models.SlugField(unique=True)
def get_absolute_url(self):
if self.region_parent is not None:
return reverse('vineyards:region', kwargs={'parent': self.region_parent.slug, 'region': self.slug})
else:
return reverse('vineyards:region-without-parent', kwargs={'region': self.slug})
class Vineyard(models.Model):
name = models.CharField(max_length=255)
text = RichTextField()
rating = models.FloatField()
custom_overlay = models.ImageField(
upload_to="custom-rating/", blank=True, max_length=255)
google_map = models.TextField()
wine_rg_url = models.URLField(blank=True)
wine_rg = models.CharField(max_length=255)
wines_url = models.URLField(blank=True)
wines = models.CharField(max_length=255)
size = models.CharField(max_length=255)
grapes = models.CharField(max_length=255)
owner_url = models.URLField(blank=True)
owner = models.CharField(max_length=255)
visits = models.CharField(max_length=255)
region = models.ForeignKey(Region, on_delete=models.CASCADE)
regions = models.ManyToManyField(
Region, blank=True, related_name="regions")
cover = models.ImageField(upload_to="vineyard/", max_length=255)
sidebar = RichTextField(blank=True)
ad_manager = models.TextField(blank=True)
meta_keywords = models.TextField(blank=True)
top_slider = models.BooleanField(default=False)
cover_slider = models.BooleanField(default=False)
hide_rating = models.BooleanField(default=False)
slug = models.SlugField(unique=True)
def get_absolute_url(self):
if self.region.region_parent is not None:
return reverse('vineyards:detail', kwargs={'parent': self.region.region_parent.slug, 'region': self.region.slug, 'slug': self.slug})
else:
return reverse('vineyards:detail-without-parent', kwargs={'region': self.region.slug, 'slug': self.slug})
And this is my urls.py:
app_name = 'vineyards'
urlpatterns = [
path('<str:parent>/<str:region>/<slug:slug>/form/',
rr_form, name="detail-form"),
path('<str:region>/<slug:slug>/form/',
rr_form, name="detail-without-parent-form"),
path('<str:parent>/<str:region>/', vineyard_region, name="region"),
path('<str:region>/', vineyard_region, name="region-without-parent"),
path('<str:parent>/<str:region>/<slug:slug>/',
vineyard_detail, name="detail"),
path('<str:region>/<slug:slug>/',
vineyard_detail, name="detail-without-parent"),
]
The problem is, I can't access the last 2 paths (vineyards: detail, vineyards: detail-without-parent). I think the problem is in the order of the urls. I have tried different order but the result is always only one or some urls are working, not all.
Is it possible to have a url with the same path like this: slug/slug/ ? Or should I split the url into two different files? Any suggestions?
Thanks.
Your url paths must be unique. How should Django otherwise know which path to use for the request?
If several paths match the url pattern, Django will use the first matching path.
Use unique url patterns in your paths. For example,
#this is just an example, adjust as it makes sense by your app logic
path('parent/<str:parent>/<str:region>/<slug:slug>/',
vineyard_detail, name="detail"),
path('detail/<str:region>/<slug:slug>/',
vineyard_detail, name="detail-without-parent"),
django masters all around the world
I'm Korean developer and started django 3 months ago.
Now I'm just a slave of my company.
Anyway, I have problem on optimizing django admin project, but no one has experienced the same problem.
This is my models "Project", "Answer", "Request".
# ------------------------------------------------------------------
# Model : Project
# Description : project model
# ------------------------------------------------------------------
class Project(models.Model):
class Meta:
verbose_name = ' project'
verbose_name_plural = ' project'
def __str__(self):
return str(self.id)
# ------------------------------------------------------------------
# Model : Request
# Description : Request model
# ------------------------------------------------------------------
class Request(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE, verbose_name='client')
project = models.ForeignKey(Project, on_delete=models.CASCADE, verbose_name='project')
product = models.ForeignKey(Subclass, on_delete=models.CASCADE, verbose_name='product')
category = models.ManyToManyField(Develop, verbose_name='category')
name = models.CharField('name', max_length=256, blank=True, null=True)
price = models.CharField('price', max_length=256, blank=True, null=True)
day = models.CharField('duedate', max_length=256, blank=True, null=True)
content = RichTextUploadingField('content', null=True)
file = models.FileField('file', upload_to=request_update_filename, blank=True, null=True)
created_at = models.DateTimeField('created_at', default=time)
add_meeting = models.BooleanField('add_meeting', default=False, null=True)
examine = models.BooleanField('check examing', default=False, null=True)
active_save = models.BooleanField('active-save', default=True, null=True)
class Meta:
verbose_name = ' request'
verbose_name_plural = ' requests'
def __str__(self):
return str(self.name)
class Answer(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE, verbose_name="client")
project = models.ForeignKey(Project, on_delete=models.CASCADE, verbose_name="project", null=True)
partner = models.ForeignKey(Partner, on_delete=models.CASCADE, verbose_name="partner")
class Meta:
verbose_name = ' Answer'
verbose_name_plural = ' Answer'
def __str__(self):
return str(self.id)
and this is my admin code
#admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
inlines = [RequestInline,AnswerInline]
list_display = ['request_name','client_email','project_price','project_created','count_answer','count_meeting','answer_status']
def request_name(self, obj):
project_id = obj.id
request_name = Request.objects.get(project = project_id)
return request_name
def client_email(self, obj):
project_id = obj.id
client = Request.objects.get(project=project_id).client
return client
def client_phone(self, obj):
project_id = obj.id
client = Request.objects.get(project=project_id).client
phone = User.objects.get(username=client).phone
return phone
def project_price(self, obj):
project_id = obj.id
request_price = Request.objects.get(project=project_id).price
return request_price
def project_created(self, obj):
project_id = obj.id
created_at = Request.objects.get(project=project_id).created_at
return created_at
def count_answer(self, obj):
project_id = obj.id
answer_qs = Answer.objects.all()
answer = Answer.objects.filter(project=project_id)
count = len(answer)
return count
def count_meeting(self, obj):
project_id = obj.id
answer_yes = Answer.objects.filter(project = project_id, state = 1)
count = len(answer_yes)
return count
def answer_status(self, obj):
project_id = obj.id
answer = Answer.objects.filter(project = project_id, info_check =1)
count = len(answer)
return count
There are many factors not included in the above, but what I want to solve is not to bring in the same queryset(Request, Answer).
The project itself is a structure that does not have attributes but is received only by foreign keys. Such a structure is making it difficult to find a solution.
I used select_related(prefetch_related too), but it does not work.
If you can give me some advice, I'd like to take some advice. thanks.
p.s. It is my first time asking question on this site, I apologize if there was anything rude.
admin.TabularInline will show the reverse foreign key in the admin detail page that may help you, but it seems that you have already used it in the inlines of ProjectAdmin.
I need to save the info of these models with foreign keys, so I created a view for Candidato, InfoPersonal and InfoAcademica, and finally I created a confirm view to save Solicitud but that page shows me:
TypeError at /solicitud/confirmacion/2/
'instance' is an invalid keyword argument for this function
My models.
project/apps/solicitud/models.py
class Candidato(models.Model):
nombre = models.CharField(max_length=50)
apellidos = models.CharField(max_length=70)
email = models.EmailField(unique=True)
def __unicode__(self):
return u'{} {}'.format(self.nombre, self.apellidos)
class InfoPersonal(models.Model):
candidato = models.ForeignKey(Candidato, null=False, blank=False, on_delete=models.CASCADE)
sexo = models.CharField(max_length=9, choices=SEXO_CHOICES)
fecha_nacimiento = models.DateField()
curp = models.CharField(max_length=18, unique=True)
pais_origen = models.CharField(max_length=30, default="México")
lugar_nacimiento = models.CharField(max_length=100)
domicilio = models.CharField(max_length=120)
codigo_postal = models.CharField(max_length=5)
telefono = models.CharField(max_length=20)
def __unicode__(self):
return u'{}'.format(self.curp)
class InfoAcademica(models.Model):
persona = models.ForeignKey(Candidato, null=True, blank=True, on_delete=models.CASCADE)
escuela_procedencia = models.CharField(max_length=50)
programa_solicitado = models.CharField(max_length=50, choices=PROGRAMA_SOLICITADO_CHOICES, default=MAS_ADMIN)
titulado = models.CharField(max_length=10, choices=ESTADO_TITULACION_CHOICES, default=YA_TITULADO)
titulacion_creditos = models.CharField(max_length=2, choices= TITULACION_CREDITOS_CHOICES, default=NO)
def __unicode__(self):
return u'{}'.format(self.programa_solicitado)
class Solicitud(models.Model):
candidato = models.ForeignKey(Candidato, null=True, blank=True)
academica = models.ForeignKey(InfoAcademica, null=False, blank=False)
Personal = models.ForeignKey(InfoPersonal, null=False, blank=False)
def __unicode__(self):
return u'Solicitud id: {}'.format(self.id)
My URLS, here I send a pk for every model to link them in Solicitud
# -*- coding: utf-8 -*-
from django.conf.urls import url
import views
app_name = 'solicitud'
urlpatterns = [
url(r'^datos_candidato/$', views.AddDatosCandidato.as_view(), name='datos_candidato'),
url(r'^datos_personales/$', views.AddDatosPersonales.as_view(), name='datos_personales'),
url(r'^datos_academicos/$', views.AddDatosAcademicos.as_view(), name='datos_academicos'),
url(r'^confirmacion/(?P<pk>\d+)/$', views.AddSolicitud.as_view(), name='datos_confirmacion'),
]
and finally my views, Here I don't know how to send the instancen of the 2 models and save it in Solicitud
project/apps/solicitud/views.py
class AddSolicitud(CreateView):
model = Solicitud, InfoPersonal, InfoAcademica
form_class = Solicitud
template_name = 'solicitud/confirmacion_solicitud.html'
You have form_class = Solicitud, but Solicitud is a model not a form.
Also, you can't specify more than one model in the model = line.
I have a problem with a m2m field that use an intermediated model ('through') with the admin and inlines. here's the code:
# MODELS
class Engagement(models.Model):
parent_engagement = models.ForeignKey('self', blank=True, null=True, related_name='child_engagements')
title = models.CharField('Engagement title', max_length=200)
...
# client
client = models.ForeignKey(Client, related_name='engagements')
primary_point_of_contact = models.ForeignKey(
ClientContact, null=True, blank=True,
related_name='engagements_for_which_point_of_contact'
)
additional_point_of_contacts = models.ManyToManyField(
ClientContact,
through='AdditionalPointOfContact'
)
.... # other fields
class ClientContact(models.Model):
first_name = models.CharField(max_length=200, blank=True)
last_name = models.CharField(max_length=200, blank=True)
jobtitle = models.CharField(max_length=200, blank=True)
company = models.ForeignKey(Client, null=True, blank=True)
class AdditionalPointOfContact(models.Model):
engagement = models.ForeignKey("Engagement", related_name='additional_points_of_contact')
client_contact = models.ForeignKey("ClientContact")
description = models.CharField(max_length=500, blank=True)
def __unicode__(self):
return self.client_contact.__unicode__()
# ADMIN
class EngagementAdmin(ChaosDefaultAdmin):
....
inlines = [
ScopeServiceElementAdmin,
AdditionalPointOfContactInlineAdmin
]
list_display = (...
class AdditionalPointOfContactInlineAdmin(admin.TabularInline):
model = AdditionalPointOfContact
fieldsets = [
('', {
'fields': (('client_contact',),
('description',),)
}),
]
extra = 0
min_num = 0
according to the django-debug-toolbar, the sql tab says 8382 queries, while commenting out AdditionalPointOfContactInlineAdmin it reduces to 10 queries, so there's something wrong there.
I might override the get_queryset method of AdditionalPointOfContactInlineAdmin, but I don't know exactly how and why. Any suggestion?
Try override EngagementAdmin.get_queryset():
class EngagementAdmin(ChaosDefaultAdmin):
def get_queryset(self, request):
qs = super(EngagementAdmin, self).get_queryset(request)
return qs.prefetch_related('additional_points_of_contact')
# or
# return qs.prefetch_related('additional_points_of_contact__client_contact')