How to call in instance of Resource in Django Tastypie.? - python

Here is my tastypie code snippet.
I have a Resource and in post_list method , an instance of Mysample is getting created there.
I want to call a method of Mysample Instance , Please help me how to do that,
please find the comment in code where I need to call the method of Mysample instance
class MysampleResource(ModelResource):
intfeild1 = fields.IntegerField('intfeild1_id', null=True)
intfeild2 = fields.IntegerField('intfeild1_id')
class Meta:
always_return_data = True
queryset = Mysample.objects.all()
allowed_methods = ['get','post','put','delete',]
authentication = SessionAuthentication()
authorization = MysampleAuthorization()
def post_list(self, request, **kwargs):
result = super(MysampleResource, self).post_list(request, **kwargs)
#here I want to call a method of Mysample Instance.
return result
Please help me , I'm begginer, so could you please give suggestion on which method to override and where should I need to do that.

You just need to add your method in your resource:
def test_method(self,param*):
#Do your stuff
return result
and within post_list you can call it like:
self.test_method(param*)
Note: The method declaration include 2 params but in python "self" is passed on as an implicit param so that when you call your method you don't pass on the self object.
= could be more than just one parameter in that case use "," in order to separate them.
If we apply all the previous concepts your code should look like:
class MysampleResource(ModelResource):
intfeild1 = fields.IntegerField('intfeild1_id', null=True)
intfeild2 = fields.IntegerField('intfeild1_id')
class Meta:
always_return_data = True
queryset = Mysample.objects.all()
allowed_methods = ['get','post','put','delete',]
authentication = SessionAuthentication()
authorization = MysampleAuthorization()
def post_list(self, request, **kwargs):
result = super(MysampleResource, self).post_list(request, **kwargs)
#Let's say that you want to pass resquest as your param to your method
method_result=self.test_method(request)
return result
def test_method(self,request):
#Do your stuff
return result

Related

DRF: How to add annotates when create an object manually?

Currently I'm trying to create an expected json to use in my test:
#pytest.mark.django_db(databases=['default'])
def test_retrieve_boards(api_client):
board = baker.make(Board)
objs = BoardSerializerRetrieve(board)
print(objs.data)
url = f'{boards_endpoint}{board.id}/'
response = api_client().get(url)
assert response.status_code == 200
But i'm receiving the following error:
AttributeError: Got AttributeError when attempting to get a value for field `cards_ids` on serializer `BoardSerializerRetrieve`.
E The serializer field might be named incorrectly and not match any attribute or key on the `Board` instance.
E Original exception text was: 'Board' object has no attribute 'cards_ids'
Currently cards_idsare added on my viewSet on get_queryset method:
def get_queryset(self):
#TODO: last update by.
#TODO: public collections.
"""Get the proper queryset for an action.
Returns:
A queryset object according to the request type.
"""
if "pk" in self.kwargs:
board_uuid = self.kwargs["pk"]
qs = (
self.queryset
.filter(id=board_uuid)
.annotate(cards_ids=ArrayAgg("card__card_key"))
)
return qs
return self.queryset
and this is my serializer:
class BoardSerializerRetrieve(serializers.ModelSerializer):
"""Serializer used when retrieve a board
When retrieve a board we need to show some informations like last version of this board
and the cards ids that are related to this boards, this serializer will show these informations.
"""
last_version = serializers.SerializerMethodField()
cards_ids = serializers.ListField(child=serializers.IntegerField())
def get_last_version(self, instance):
last_version = instance.history.first().prev_record
return HistoricalRecordSerializer(last_version).data
class Meta:
model = Board
fields = '__all__'
what is the best way to solve it? I was thinking in create a get_cards_ids method on serializer and remove annotate, but I don't know how to do it and justing googling it now. rlly don't know if this is the correct way to do it.
Test the view, not the serializer, i.e. remove BoardSerializerRetrieve(board) from your test code.
cards_ids is annotated on ViewSet level. The annotated queryset is then passed to serializer.
#pytest.mark.django_db(databases=['default'])
def test_retrieve_boards(api_client):
board = baker.make(Board)
url = f'{boards_endpoint}{board.id}/'
response = api_client().get(url)
assert response.status_code == 200
Also, instead of building the URL manually with url = f'{boards_endpoint}{board.id}/', consider using reverse, e.g. url = reverse("path-name", kwargs={"pk": board.id}).

get() returned more than one-- Django Restframework

I have a Django model which needs to have more than 1 images and more than 1 files (numbers may vary as per requirement), for which I adjusted my Admin Panel accordingly like this
models.py
class MasterIndividualMembers(models.Model):
individualmemberId = models.CharField(primary_key=True, max_length=100, default=1)
...
...
def __str__(self):
return self.firstname + " " + self.lastname
class IndividualMemberPhotos(models.Model):
individualmemberId = models.ForeignKey(MasterIndividualMembers, default=None,on_delete=models.CASCADE)
image = models.ImageField(upload_to="individualmemberphotos/")
class IndividualMemberCatalogue(models.Model):
individualmemberId = models.ForeignKey(MasterIndividualMembers, default=None,on_delete=models.CASCADE)
files = models.FileField(upload_to="individualmembercatalogue/")
admin.py
class IndividualMemberPhotosAdmin(admin.StackedInline):
model = IndividualMemberPhotos
class IndividualMemberCatalogueAdmin(admin.StackedInline):
model = IndividualMemberCatalogue
#admin.register(MasterIndividualMembers)
class MasterIndividualMembersAdmin(admin.ModelAdmin):
inlines = [IndividualMemberPhotosAdmin,IndividualMemberCatalogueAdmin]
class Meta:
model = MasterIndividualMembers
For the views I simply make a function to provide details of all the Images, Document and that User
views.py
#csrf_exempt
#api_view(['POST'])
#permission_classes([IsAuthenticated])
def get_individualmember(request):
if request.method == 'POST':
try:
individualmemberId = request.POST.get('individualmemberId')
result = {}
result['individualMemberDetails'] = json.loads(serializers.serialize('json', [MasterIndividualMembers.objects.get(individualmemberId=individualmemberId)]))
result['individualPhotoDetails'] = json.loads(serializers.serialize('json', IndividualMemberPhotos.objects.filter(individualmemberId__individualmemberId = individualmemberId)))
result['individualCatalogueDetails'] = json.loads(serializers.serialize('json', IndividualMemberCatalogue.objects.filter(individualmemberId__individualmemberId = individualmemberId)))
except Exception as e:
return HttpResponseServerError(e)
Problem: While fetching the details for any individual member, it throws an error get() returned more than one IndividualMemberPhotos -- it returned 2!, which is expected to have more than 1 objects.
How can I make the Restframework to provide me details of all image object together.
Instead of using get() which strictly returns a single element, use filter() which returns 0 or more elements.
As documented in https://docs.djangoproject.com/en/3.2/topics/db/queries/#retrieving-a-single-object-with-get
filter() will always give you a QuerySet, even if only a single object
matches the query - in this case, it will be a QuerySet containing a
single element.
If you know there is only one object that matches your query, you can
use the get() method on a Manager which returns the object directly:
The behavior you are experiencing is actually documented here https://docs.djangoproject.com/en/3.2/ref/models/querysets/#django.db.models.query.QuerySet.get
If get() finds more than one object, it raises a
Model.MultipleObjectsReturned exception:

How to use a function to pass the result to 'queryset'?

I'm working on a Python/Django project. I have to use the YearArchiveView base class, so I have this:
class ArchiveView(YearArchiveView):
queryset = ArticlePage.objects.all()
make_object_list = True
date_field = 'date'
template_name='btcmag/pages/archives_list.html'
allow_future = False
context_object_name = 'articles'
def extract_month(self, article):
'extracts the starting date from an entity'
return article.date.month
def extract_year(self, article):
'extracts the starting date from an entity'
return article.date.year
Instead of having queryset = ArticlePage.objects.all(), I would like to have a function returning the correct Queryset. Something like:
queryset = getQuerySet()
At the same time I have to pass in some parameters.
I tried defining the function within the class, calling it with self and alone, but I get that the function or self are not defined.
Where do I have to define the function/method?
How can I pass it to queryset?
Instead of having queryset set, in Django views you can overwrite/use the get_queryset method:
class ArchiveView(YearArchiveView):
def get_queryset(self):
...magic here...
return custom_queryset

Can't add extra argument to Python(Django) function call

I need to serialize data with a serialiser and also I have a file for saving but I can't path the extra varible with file to my serializer
issue_dict = request.data.get('issue')
file = request.data.get('file')
This is working fine:
serializer = WriteIssueSerializer(data=issue_dict, context=self.get_serializer_context())
This is what I'd like to get, but it says "got an unexpected keyword argument 'file'" :
serializer = WriteIssueSerializer(data=issue_dict, file=file, context=self.get_serializer_context())
I understand that inside the serializer I should define variable "file",
so look at this serializer:
class WriteIssueSerializer(serializers.ModelSerializer):
notes = IssueNoteSerializer(many=True)
def create(self, val):
issue_dict = val.get('issue')
# issue_dict['assigned_to'] = issue_dict['assigned_to']['id']
# issue_dict['reported_by'] = issue_dict['reported_by']['id']
assigned_to_id = issue_dict.pop('assigned_to').id
reported_by_id = issue_dict.pop('reported_by').id
notes_info = issue_dict.pop('notes')
# print(validated_data.pop('file'))
issue = Issue.objects.create(assigned_to_id=assigned_to_id, reported_by_id=reported_by_id, **issue_dict)
for note_info in notes_info:
note = IssueNote.objects.create(**note_info)
note.issue = issue
It's obvious that changing from
def create(self, val): to def create(self, val, file): will fix my error, but not, the error is still the same
serializer = WriteIssueSerializer(data=issue_dict, file=file, context=self.get_serializer_context())
This calls the constructor of WriteIssueSerializer (__init__()), not .create(). So you have to create the extra argument in there, or call .create().

Django Call Class based view from another class based view

i am trying to call a class based view and i am able to do it, but for some reason i am not getting the context of the new class that i am calling
class ShowAppsView(LoginRequiredMixin, CurrentUserIdMixin, TemplateView):
template_name = "accounts/thing.html"
#method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super(ShowAppsView, self).dispatch(*args, **kwargs)
def get(self, request, username, **kwargs):
u = get_object_or_404(User, pk=self.current_user_id(request))
if u.username == username:
cities_list=City.objects.filter(user_id__exact=self.current_user_id(request)).order_by('-kms')
allcategories = Category.objects.all()
allcities = City.objects.all()
rating_list = Rating.objects.filter(user=u)
totalMiles = 0
for city in cities_list:
totalMiles = totalMiles + city.kms
return self.render_to_response({'totalMiles': totalMiles , 'cities_list':cities_list,'rating_list':rating_list,'allcities' : allcities, 'allcategories':allcategories})
class ManageAppView(LoginRequiredMixin, CheckTokenMixin, CurrentUserIdMixin,TemplateView):
template_name = "accounts/thing.html"
def compute_context(self, request, username):
#some logic here
if u.username == username:
if request.GET.get('action') == 'delete':
#some logic here and then:
ShowAppsView.as_view()(request,username)
What am i doing wrong guys?
Instead of
ShowAppsView.as_view()(self.request)
I had to do this
return ShowAppsView.as_view()(self.request)
Things get more complicated when you start using multiple inheritance in python so you could easily be trampling your context with that from an inherited mixin.
You don't quite say which context you are getting and which one you want (you're not defining a new context), so it's difficult to completely diagnose, but try rearranging the order of your mixins;
class ShowAppsView(LoginRequiredMixin, CurrentUserIdMixin, TemplateView):
this implies that LoginRequiredMixin will be the first class to inherit from, and so it will take precedence over the others if it has the attribute you're looking for - if it hasn't then python will look in CurrentUserIdMixin and so on.
If you want to be really sure that you get the context that you're after, you could add an override like
def get_context(self, request):
super(<my desired context mixin>), self).get_context(request)
to ensure that the context you get is the one from the mixin that you want.
* Edit *
I don't know where you've found compute_context but it's not a django attribute so will only get called from ShowAppsView.get() and never in ManageAppView.

Categories

Resources