I am making a webapp with Django Framework. I am making a form for creating new "incidents" (this form is using a model called NewIncidents). I am trying to take the values under "title" from my IncidentsType table, and use them as options for a Select menu in the form. But, something weird happens: in the form, the options appear, but when you submit the form and check how it was submitted (in the admin panel), it shows the .object(n) instead of the name of the option.
For example: Result of one submit : in the form showed the correct selection name, which was "Internet", but after submitting, in the admin panel, it showed IncidentsType object (3).
My models:
from django.db import models
class NewUsers(models.Model):
name = models.CharField(max_length=38)
user_name = models.CharField(max_length=35)
class NewIncidents(models.Model):
tipo = models.CharField(max_length = 50)
titulo = models.CharField(max_length = 200)
resolucion = models.CharField(max_length = 300)
class IncidentsType(models.Model):
title = models.CharField(max_length = 200)
subtitle = models.CharField(max_length = 200)
description = models.CharField(max_length = 400)
My form:
from django import forms
from django.db import models
from .models import NewIncidents, IncidentsType
class IncidentForm(ModelForm):
incidents = IncidentsType.objects.all()
eleji = []
for incident in incidents:
ttype = incident.title
num = str(incident)
conjunto = (num, ttype)
eleji.append(conjunto)
tipo = forms.ChoiceField(choices=eleji)
class Meta:
model = NewIncidents
fields = ('tipo', 'titulo', 'resolucion')
labels = {
'tipo': 'Tipo de Incidente:',
'titulo': 'Resumen del Incidente:',
'resolucion': 'Resolucion del Incidente:',
}
widgets = {
'tipo': forms.Select(attrs={'class' : 'form-control'}),
'titulo': forms.TextInput(attrs={'class' : 'form-control'}),
'resolucion': forms.TextInput(attrs={'class' : 'form-control'}),
}
on your models try defining the str function to help django better represent the objects of the model in the admin page
example for the IncidentsType:
class IncidentsType(models.Model):
title = models.CharField(max_length = 200)
subtitle = models.CharField(max_length = 200)
description = models.CharField(max_length = 400)
def __str__(self):
return self.title
basicly this function should return a string that represents the object like a name or a title
you can read more about it in the docs here
Related
I am working with django rest_framework and im stuck here. Im new to django so please bear with me. Im trying to get the coordinates of my current user, then listing all the studios from closest to farthest away. Im using GeoDjango's Point function to convert the user and studio models longitude and latitude into a Point by defining a property in the models. Then im serializing the property field so my API View can compute distance from the user location to all the studio locations. This is the part where I am stuck at. I get "TypeError: Distance function requires a geometric argument in position 1". I also get "TypeError: Object of type Point is not JSON serializable when I call queryset = Studio.objects.all()"
In summary im trying to list all the studios based on geographical proximity to a the user location and list them in order from closest to farthest away. Pls help
Models
class Studio(models.Model):
name = models.CharField(max_length=120, primary_key=True)
address = models.CharField(max_length=120)
lon = models.FloatField()
lat = models.FloatField()
postal_code = models.CharField(max_length=7)
phone_num = models.CharField(max_length=12)
images = models.ImageField(upload_to='studios')
#property
def studio_loc(self):
studio_location = Point(self.lon, self.lat)
return studio_location
class User(AbstractUser):
first_name = models.CharField(max_length=120, null=True)
last_name = models.CharField(max_length=120, null=True)
email = models.EmailField(max_length=120, unique=True)
avatar = models.ImageField(null=True)
phone_num = models.IntegerField(null=True)
username = None
password = models.CharField(max_length=120)
lon = models.FloatField(null=True)
lat = models.FloatField(null=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
#property
def user_loc(self):
user_location = Point(self.lon, self.lat)
return user_location
serializers.py
class UserLocationSerializer(serializers.ModelSerializer):
user_loc = serializers.SerializerMethodField()
class Meta:
model = User
fields = ('email', 'user_loc')
def get_user_loc(self, obj):
point = obj.user_loc()
print(point)
return point
class StudiosForUserSerializer(serializers.Serializer):
studio_loc = serializers.SerializerMethodField()
class Meta:
model = Studio
fields = ('name', 'address', 'postal_code', 'phone_num', 'images', 'studio_loc')
def get_studio_loc(self, obj):
point = obj.studio_loc()
print(point)
return json.dumps(point)
view.py
class StudiosForUserView(ListAPIView):
permission_classes = [IsAuthenticated]
serializer_class = StudiosForUserSerializer
def get_queryset(self):
user_serializer = UserLocationSerializer(self.request.user)
user_location = user_serializer['user_loc']
queryset = Studio.objects.annotate(distance=Distance(self.serializer_class["studio_loc"], user_location)).order_by("distance")[0:3]
#queryset = Studio.objects.all()
print(queryset)
return queryset
urls.py
urlpatterns = [
path('all/', StudiosForUserView.as_view()),
]
Been trying to show the created_date of the customer order on another view, kindly help much appreciated.
ListListView
class ListListView(generic.ListView):
model = HBTYList
template_name = "accounts/modals/nomodal/index.html"
paginate_by = 3
def get_queryset(self):
qs = self.model.objects.all().order_by('-id')
p_f = HbtyCustomerListFilter(self.request.GET, queryset=qs)
return p_f.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['dc'] = HBTYItem.objects.filter(hbty_cust_id=self.kwargs["list_id"]) #Fix this method to show created_data
context['filter'] = HbtyCustomerListFilter(self.request.GET, queryset=self.get_queryset())
return context
ItemListView
class ItemListView(ListView):
model = HBTYItem
template_name = "accounts/modals/nomodal/todo_list.html"
paginate_by = 2
ordering = ['id']
def get_queryset(self):
return HBTYItem.objects.filter(hbty_cust_id=self.kwargs["list_id"])
def get_context_data(self):
context = super().get_context_data()
context['t_sum'] = HBTYItem.objects.filter(hbty_cust_id=self.kwargs["list_id"]).aggregate(Sum('price'))
context["hbty_list"] = HBTYList.objects.get(id=self.kwargs["list_id"])
return context
Urls.py
path("hbtylist/", views.ListListView.as_view(), name="hbtylist"),
path("list/<int:list_id>/", views.ItemListView.as_view(), name="list"),
# CRUD URL FOR HBTYCUSTOMERS
path("list/add/", views.ListCreate.as_view(), name="list-add"),
path("list/<int:pk>/delete/", views.ListDelete.as_view(), name="list-delete"),
# CRUD URL FOR HBTYCUSTOMERSAPPOINMENTS
path("list/<int:list_id>/item/add/", views.ItemCreate.as_view(),name="item-add",),
path("list/<int:list_id>/item/<int:pk>/",views.ItemUpdate.as_view(),name="item-update",),
path("list/<int:list_id>/item/<int:pk>/delete/",views.ItemDelete.as_view(),name="item-delete",),
Thank You For The Help.
There are 3 models (companies, divisions and staffgroups) to display as list.
I am trying to create a class base view extended from ListView to list various models through passing the model name in the URLpatterns.
I had created individual class view for each model but there are essentially copy paste codes. Is there a way to streamline the code into just one class and get the model from urlpath.
models.py
from django.db import models
...
class Company(models.Model):
id = models.CharField(max_length=5, primary_key=True)
name = models.CharField(max_length=100)
is_active = models.BooleanField()
...
class Division(models.Model):
id = models.CharField(max_length=5, primary_key=True)
name = models.CharField(max_length=100)
is_active = models.BooleanField()
...
class StaffGroup(models.Model):
name = models.CharField(max_length=20)
is_active = models.BooleanField()
...
urls.py
from django.urls import path
from srrp.views import srrpIndexView, srrpListView
app_name = 'srrp'
urlpatterns = [
path('', srrpIndexView.as_view(), name='srrp_index'),
path('<str:modelname>', srrpListView.as_view(), name='srrp_list'),
]
views.py
class srrpListView(ListView):
template_name = 'srrp/srrplist.html'
model = self.kwargs['modelname'] # I know this is wrong, this is just placeholder for the right solution
paginate_by = 10
Subclass get_queryset. (Bookmark Classy Class-based views)
def get_queryset(self):
model = self.kwargs['modelname']
if model == 'foo':
return Foo.objects.all()
if model == 'bar':
return Bar.objects.all()
if model == 'green_bar':
return Bar.objects.filter( colour='green' )
...
raise ValueError(
f'This shouldn't be possible: model = "{model}"'
If you don't want any "special" models, you could either look up the right model in a dict of classes:
klass = MODEL_CLASSES[model] # KeyError if bad model in URL
return klass.objects.all()
or you could use a Django function whose name I have forgotten to get the model class by app and model names.
Solved.
views.py
class srrpListView(ListView):
template_name = 'srrp/srrplist.html'
paginate_by = 10
def get_queryset(self):
modelname = self.kwargs['modelname']
ctype = ContentType.objects.get(app_label='srrp', model=modelname)
model = ctype.model_class()
return model.objects.all()
I defined a model named Emp (employees) as below:
from django.db import models
from django.contrib.auth.models import User
class Emp(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
empid = models.PositiveIntegerField(unique=True)
cnname = models.CharField(max_length=20)
gender = models.BooleanField(default=True)
birthdate = models.DateField(default=None, blank=True, null=True)
joindate = models.DateField()
islogi = models.BooleanField(default=True)
isleave = models.BooleanField(default=False)
leavedate = models.DateField(default=None, blank=True, null=True)
In Admin.py I have following code:
from django.contrib import admin
from django.contrib.auth import get_user_model
from .models import Emp
class EmpAdmin(admin.ModelAdmin):
list_display = ('id','empid','cnname','gender','birthdate','joindate',
'islogi','isleave','leavedate')
ordering = ('empid',)
search_fields = ['empid','cnname']
list_per_page = 12
exclude = ('isleave','leavedate',)
# for list view, if not admin just show emp self info
# for admin all employees will be listed.
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
else:
user = get_user_model()
return qs.filter(empid=Emp.objects.get(user_id=user.objects.get(username=request.user).id).empid)
# this is used for form add and change actions
# but I want to add and change have different option list
# add just list the users which are not employees
# change list the users which are not employees + employee self
def formfield_for_foreignkey(self, db_field, request, **kwargs):
print("self", self)
print("db_field", db_field)
print("build_absolute_uri() => ", request.build_absolute_uri())
if db_field.name == 'user':
print("kwargs => ", kwargs)
users = get_user_model()
u = users.objects.all()
uidlist = []
for x in range(len(u)):
uidlist.append(u[x].id)
e = Emp.objects.all()
for x in range(len(e)):
uidlist.remove(e[x].user_id)
kwargs["queryset"] = users.objects.filter(id__in=uidlist)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
admin.site.register(Emp, EmpAdmin)
Above "formfield_for_foreignkey" it list the same option list for "user" option list. How can I override the list for "add" and "change" actions, so they can use different option lists?
You could use the request that is passed in to check if the request is a change or add:
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if "/add/" in request.path:
#add logic
elif "/change/" in request.path:
#change logic
For flask-admin the following only gives me CRUD access to Task and the TaskItem embedded document, but no access to ItemParameter or ItemTitle. Is this not supported in flask-admin or am I doing something wrong? Thx
class TaskItem(db.EmbeddedDocument):
type = db.StringField(max_length = 32)
column = db.IntField()
row = db.IntField()
width = db.IntField()
height = db.IntField()
meta = {'allow_inheritance': True}
class ItemParameter(TaskItem):
label = db.StringField(max_length = 32)
formula = db.StringField(max_length = 256)
parameter = db.ReferenceField(Parameter)
class ItemTitle(TaskItem):
label = db.StringField(max_length = 32)
document = db.ReferenceField(Document)
class Task(db.Document):
items = db.ListField(db.EmbeddedDocumentField(TaskItem))
def __unicode__(self):
return unicode(self.name)
# Flask-Admin
class SecuredModelView(ModelView):
def is_accessible(self):
return current_user.has_role('admin')
admin.add_view(SecuredModelView(Task))
As stated by the flask-admin creator this feature is not yet supported.
https://github.com/flask-admin/flask-admin/issues/907