Create django object using a view with no form - python

I was wondering how I would be able to create an object in a database based the URL a user is going to.
Say for example they would go to /schedule/addbid/1/ and this would create an object in the table containing the owner of the bid, the schedule they bidded on and if the bid has been completed. This here is what I have for my model so far for bids.
class Bids(models.Model):
id = models.AutoField("ID", primary_key=True, editable=False,)
owner = models.ForeignKey(User)
biddedschedule = models.ForeignKey(Schedule)
complete = models.BooleanField("Completed?", default=False)
The biddedschedule would be based on the number in the URL as the 1 in this case would be the first schedule in the schedule table
Any ideas on how to do this?

You should get the id parameter using urls.py:
#urls.py
from appname.views import some_view
urlpatterns = patterns('',
url(r'^schedule/addbid/(?P<id>\d+)$', some_view),
...
)
Take a look at the documentation about capturing parameters in the urlconf.
And then, in views.py you should construct a Bids Object using the id passed in the URL, the currently logged in user (request.user), and the biddschedule from your DB. For example:
#views.py
def some_view(request, id):
if request.user.is_authenticated():
# get the biddschedule from your DB
# ...
bids = models.Bids(id=id, owner=request.user, biddedschedule=biddedschedule)
bids.save()
return HttpResponse("OK")
return Http404()

Catch the number via the urlconf. Get the current user via request.user. Create a model instance by calling its constructor, and save it to the database via its save() method.

`#view.py under a post or get method`
new_bird, created = Bids.objects.get_or_create(
owner = user_obj,
biddedschedule = biddedschedule_obj,
complete = bool
)
new_bird.save()

Related

How can I get a parameter of an url with django-rest-framework

I am building a map with different station location.
The stations belong to different fields.
I have to show all station and, I have all station of a field.
At some point my api is called
"""Markers API URL Configuration."""
# Maps with Django (2)
# https://www.paulox.net/2021/07/19/maps-with-django-part-2-geodjango-postgis-and-leaflet/
from rest_framework import routers
from map.viewsets import MarkerViewSet
router = routers.DefaultRouter()
router.register(r"map", MarkerViewSet)
urlpatterns = router.urls
then the MarkerViewSet is called (viewsets.py)
class MarkerViewSet(viewsets.ReadOnlyModelViewSet):
"""Marker view set."""
#print(self.kwargs.get('idfield'))
bbox_filter_field = "location"
filter_backends = (filters.InBBoxFilter,)
queryset = Stations.objects.filter(station_active=1, map=1)
serializer_class = StationsSerializer
def get_queryset(self, **kwargs):
#field_id = self.kwargs['idfield']
#print("pp:", self.kwargs)
return Stations.objects.filter(fields_id_field=1)
The code above works, but it only show the markers of the field 1
If I change this to 2
return Stations.objects.filter(fields_id_field=2)
It show all station of the field with the id 2
My url is as the follwoing http://127.0.0.1:8080/map/ to print all stations of all fields.
If I want to have the stations of the field 1, my url will be
http://127.0.0.1:8080/map/1/field
and for the field 2 and 4
http://127.0.0.1:8080/map/2/field
http://127.0.0.1:8080/map/4/field
My problem, I can not not and I do not know of to get the id 1,2,4 or another form my url
this does not work
#field_id = self.kwargs['idfield']
#print("pp:", self.kwargs)
Here is my map/urls.py
an my project urls.py
Should I try to get the id of the field from the viewsets.py or how would you suggest me to archive my goal?
EDIT:
Here is my views.py. Here I can get idfield
Would it have a way to pass it my viewsets.py?
I beleive that your proposition only works in views.py as it start with
def field(request, idfield):
request.GET.get("idfield")
isn't?
I am working with a viewsets.py starting with
class MarkerViewSet(viewsets.ReadOnlyModelViewSet):
"""Marker view set."""
bbox_filter_field = "location"
filter_backends = (filters.InBBoxFilter,)
queryset = Stations.objects.filter(station_active=1, map=1)
serializer_class = StationsSerializer
"""
def get_tags(self):
return Stations.objects.filter(fields_id_field=1)
"""
def get_queryset(self):
#field_id = self.kwargs['idfield']
#print("ppp:", self.kwargs['idfield'])
return Stations.objects.filter(fields_id_field=1)
I do know where your proposition could be added.
However, I think I am getting close to the solution, but I still get error.
I hope you can help me
First, in my map.js file. I added
async function load_markers() {
const markers_url = `/api/map/1/`; // LOOK AT THIS LINE
console.log("markers_url: ",markers_url);
const response = await fetch(markers_url);
//console.log("response: ",response);
const geojson = await response.json();
console.log("geojson: ",geojson);
return geojson;
}
In my urls.py file, I changed to
path("api/<int:idf>/", include("map.api")),
which will redirect to the api.py file. I think, all is correct until this point, isn't?
In my api.py file, I have tried serveral things getting inspirated from the django-rest-framework - router page
router = routers.DefaultRouter()
#router.register(r"map", MarkerViewSet) #INITIAL
#router.register(r"^map/{idf}/$", MarkerViewSet) #I tried this
#router.register(r"^map/(?P<idf>[0-9]+)/$", MarkerViewSet) #this generate an error because of idf
router.register(r"^map/(?P<id_f>[0-9]+)/$", MarkerViewSet)
urlpatterns = router.urls
Another error message is on Firefox:
enter image description here
I believe, I should find the right format, but something else should be wrong
Many thanks for your help
Args
I believe you API urls should be as follows
/maps/ --> returns a list of objects
/maps/<id>/ --> returns a single object
If you do this you should be able to get results according to the given id (if primary key) without doing anything in your view. viewsets automatically returns an object based on the lookup field. If it is not a primary key you can set different lookup field.
Kwargs
in kwargs your URL should be as /maps/?idfield=<id>, then you will be able to do the followings.
kwargs from GET request can be obtained as below
request.GET.get("idfield")

Django How do I show Author (user) name instea of ID?

I have a custom user model (CustomUsers) on one app called users, and then I have a model called Bookings from which I have created a ModelfForm called BookingsForm.
In the Bookings model (and ultimately the BookingsForm), I have a field called booking_author which has a ForeignKey inherited from the CustomUsers model.
Now I have been able to successfully call the booking_author field into my bookingscreate view and make it uneditable/read only as I had wanted. The issue now is that the field is displaying the id of the author instead of the name of the author. Is anyone able to help me resolve this?
views.py
#login_required
def bookingscreate(request):
bookings_form = BookingsForm(initial={'booking_author': request.user })
context = {
'bookings_form': bookings_form
}
return render(request, 'bookings_create.html', context)
There are multiple ways of getting the users name. To obtain the user name in this case you could use
request.user.get_full_name()
request.user.get_short_name()
Explanation:
request.user is the User object, and thus you have access to all user methods. If the above is not what you're looking for you could create a method in your user class and then call that method in this view.

Using ManyToManyFields() with Django

I'm building a social network where user are supposed to be able to follow each other. So I define a class user with a field: ManyToMany to stock the users that follow this user. This is what I have done in my model.py:
followings = models.ManyToManyField('self', blank=True)
This is my view.py:
#login_required
def follow_test(request):
name = request.POST.get('name', '')
user_followed = Dater.objects.get(username=name)
current_user = Dater.objects.get(id=request.user.id)
print current_user.followings # display my_app.Dater.None
current_user.followings.add(user_followed)
print current_user.followings # display my_app.Dater.None
I retrieve correctly my users (current (The one who follow someone) and the followed one) but I can't add the followed user in the set followings of the current user. Can you see something I don't do properly in my view?
followings is a manager; to show the members of that relationship, you need to call .all() on it (or another manager/queryset method like order_by).
print current_user.followings.all()

Django Restframework: update an object without accesing specific object id

I am using Django with Restframework, and I want to update a certain object. I have the following model:
class PromotionalCode(models.Model):
promotional_code = models.CharField(max_length=10, default=random_with_letters(), unique=True)
myuser = models.ForeignKey('MyUser', related_name='promotional_code_user', blank=True, null=True)
promotion_type = models.PositiveIntegerField(default=1)
time_transaction = models.DateTimeField(default=datetime.now())
used = models.BooleanField(default=False)
The following viewset:
class UpdateOnlyDetailViewSet(mixins.UpdateModelMixin,
viewsets.GenericViewSet):
pass
The following view:
class PromotionalCodeViewSet(UpdateOnlyDetailViewSet):
queryset = PromotionalCode.objects.all()
serializer_class = PromotionalCodeSerializer
permission_classes = (IsOwnerOrReadOnly,)
And it has the following url:
router = DefaultRouter()
router.register(r'promotionalcode', views.PromotionalCodeViewSet)
I can only update the Promotionalcode object when I access to
/promotionalcode/code_id
and I want to update a certain code when I access to
/promotionalcode/
without specifying the id. What I have to do for do it?
I have found 3 solutions to my problem. I have tested 2 of them:
First solution: I have created another model called PromotionalCodesHistory(models.Model) with the same attributes as PromotionalCode and create a serializer with the method create, creating a PromotionalCodesHistory instance and call update method to update PromotionalCode. Then, when I access to the url /promotional/ I can update Promotional code.
Second solution: Modify DefaultRouter() to access to update on /promotional/ url, by the following code:
from rest_framework.routers import DefaultRouter
class CustomUpdateRouter(DefaultRouter):
routes = [
# List route.
Route(
url=r'^{prefix}{trailing_slash}$',
mapping={
'get': 'list',
'post': 'create',
'put': 'update',
'patch': 'partial_update',
},
name='{basename}-list',
initkwargs={'suffix': 'List'}
),
# Dynamically generated list routes.
# Generated using #list_route decorator
# on methods of the viewset.
DynamicListRoute(
url=r'^{prefix}/{methodname}{trailing_slash}$',
name='{basename}-{methodnamehyphen}',
initkwargs={}
),
# Detail route.
Route(
url=r'^{prefix}/{lookup}{trailing_slash}$',
mapping={
'get': 'retrieve',
'delete': 'destroy'
},
name='{basename}-detail',
initkwargs={'suffix': 'Instance'}
),
# Dynamically generated detail routes.
# Generated using #detail_route decorator on methods of the viewset.
DynamicDetailRoute(
url=r'^{prefix}/{lookup}/{methodname}{trailing_slash}$',
name='{basename}-{methodnamehyphen}',
initkwargs={}
),
]
Then, on view class, reimplement the get_object method to specify your own filters to get the object, you can access to get_serializer_context method to get context data, the filter is specified using a dictionary of unicode, as the following:
{u'key': unicode(variable1), u'key2': unicode(variable2)}
Third solution: Last solution which I have not tested, is to change the primary key to promotional_code field, to access promotional code, using /promotionalcode/promotional_code

Inline-like solution for Django Admin where Admin contains ForeignKey to other model

I have several Customers who book Appointments. Each Appointment has exactly one customer, though a customer can be booked for multiple appointments occurring at different times.
class Customer(model.Model):
def __unicode__(self):
return u'%s' % (self.name,)
name = models.CharField(max_length=30)
# and about ten other fields I'd like to see from the admin view.
class Appointment(models.Model):
datetime = models.DateTimeField()
customer = models.ForeignKey("Customer")
class Meta:
ordering = ('datetime',)
Now when an admin goes to browse through the schedule by looking at the Appointments (ordered by time) in the admin, sometimes they want to see information about the customer who has a certain appointment. Right now, they'd have to remember the customer's name, navigate from the Appointment to the Customer admin page, find the remembered Customer, and only then could browse their information.
Ideally something like an admin inline would be great. However, I can only seem to make a CustomerInline on the Appointment admin page if Customer had a ForeignKey("Appointment"). (Django specifically gives me an error saying Customer has no ForeignKey to Appointment). Does anyone know of a similar functionality, but when Appointment has a ForeignKey('Customer')?
Note: I simplified the models; the actual Customer field currently has about ~10 fields besides the name (some free text), so it would be impractical to put all the information in the __unicode__.
There is no easy way to do this with django. The inlines are designed to follow relationships backwards.
Potentially the best substitute would be to provide a link to the user object. In the list view this is pretty trivial:
Add a method to your appointment model like:
def customer_admin_link(self):
return 'Customer' % reverse('admin:app_label_customer_change %s') % self.id
customer_admin_link.allow_tags = True
customer_admin_link.short_description = 'Customer'
Then in your ModelAdmin add:
list_display = (..., 'customer_admin_link', ...)
Another solution to get exactly what you're looking for at the cost of being a bit more complex would be to define a custom admin template. If you do that you can basically do anything. Here is a guide I've used before to explain:
http://www.unessa.net/en/hoyci/2006/12/custom-admin-templates/
Basically copy the change form from the django source and add code to display the customer information.
Completing #John's answer from above - define what you would like to see on the your changelist:
return '%s' % (
reverse('admin:applabel_customer_change', (self.customer.id,)),
self.customer.name # add more stuff here
)
And to add this to the change form, see: Add custom html between two model fields in Django admin's change_form
In the ModelAdmin class for your Appointments, you should declare the following method:
class MySuperModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if obj:
# create your own model admin instance here, because you will have the Customer's
# id so you know which instance to fetch
# something like the following
inline_instance = MyModelAdminInline(self.model, self.admin_site)
self.inline_instances = [inline_instance]
return super(MySuperModelAdmin, self).get_form(request, obj, **kwargs)
For more information, browser the source for that function to give you an idea of what you will have access to.
https://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py#L423
There is a library you can use it.
https://github.com/daniyalzade/django_reverse_admin
But if you want to use link to object in showing table you can like this code:
def customer_link(self, obj):
if obj.customer:
reverse_link = 'admin:%s_%s_change' % (
obj.customer._meta.app_label, obj.customer._meta.model_name)
link = reverse(reverse_link, args=[obj.customer.id])
return format_html('More detail' % link)
return format_html('<span >-</span>')
customer_link.allow_tags = True
customer_link.short_description = 'Customer Info'
And in list_display:
list_display = (...,customer_link,...)

Categories

Resources