0

I have a model, 'Project'. The idea is that, a user will log in and create a project. After creating, the user will work on this project at any time. Certain details will be saved to other models where I have written custom functions for it in Serializers.py.

In order solve the idea I have, I need to retrieve the id of the current project that the user is currently working on in Serializers.py. Below is my code:

View.py

class MaterialTagExcelViewSet(FilteredModelViewSet):
    queryset = MaterialTagExcel.objects.all()
    serializer_class = MaterialTagExcelSerializer
    permission_classes = (IsAuthenticated,)
    http_method_names = ('get', 'head', 'post', 'options', 'patch')

Serializers.py

class MaterialTagExcelSerializer(BaseSerializer):

    class Meta:
        fields = "__all__"
        model = MaterialTagExcel

    def create(self, validated_data):
        name = validated_data.get('name')  # get current material name

        if name is not None: 
            name_tag = MaterialTagExcel.objects.filter(name=name).first()  # filter name to check if it already exists

            client = self.context['request'].user.profile.client  # get current client details

            if name_tag is not None:  # if name exists
                objects = MaterialExcelClient.objects.filter(client_id=client.id, name_id=name_tag.id)

                if objects.count() == 0:
                    material_excel_client = MaterialExcelClient(client_id=client.id, name_id=name_tag.id)
                    material_excel_client.save()  # get current id and mat id and save to material_client_excel
                    return MaterialExcelClient.objects.filter(name_id=name_tag.id).order_by('-id')[0]
                else:
                    return MaterialExcelClient.objects.filter(client_id=client.id, name_id=name_tag.id).first()

            else:
                MaterialTagExcel.objects.create(**validated_data)
                MaterialTagExcel.objects.all()  # save if material is new and does not exist

                # return the id of this newly created material
                obj = MaterialTagExcel.objects.filter(name=name).order_by('-id')[0]
                # save the id of the newly created material and current client id into material_excel_client
                material_excel_client = MaterialExcelClient(client_id=client.id, name_id=obj.id)
                material_excel_client.save()
                return MaterialExcelClient.objects.filter(name_id=obj.id).order_by('-id')[0]

From above serializer, I am able to get the client.id with the help of CurrentUserDefault. In my table user is related to profile and profile is related to client but not project. I tried to with a custom CurrentProjectDefault, but I didnt succeeded. I tried with many online sources to solve my problem.

Is there any way to get the id of the current object from client ? I am apologizing in advance if the solution to my problem is very simple.

If you would need some more details, kindly write it in comment.

Thanks in advance.

Models.py

class MaterialTagExcel():
    name = models.CharField(max_length=255, verbose_name='name', null=False, blank=False) 

    def __str__(self):
        return "Material %s: %s" % (self.id, self.name)

    @classmethod
    def get_queryset_for_user(cls, user):
        return cls.objects.all()

class Project():
    client =    models.ForeignKey(Client, related_name='projects', on_delete=models.PROTECT)

    name =                models.CharField(max_length=255)

class ToDo(BaseModel):
    project = models.ForeignKey(Project, related_name='todos', on_delete=models.CASCADE)
    owner_client = models.ForeignKey(Client, related_name='todos', on_delete=models.CASCADE)




Jayanta
  • 21
  • 4
  • Could you post your `Project` model? And to what model a `Project` is linked ? A user ? A profile ? – frankie567 Oct 17 '19 at 12:30
  • Hi frankie567, project is not linked to user or profile, client is linked to project and I am trying to excess with its reverse relation but getting an error. – Jayanta Oct 17 '19 at 13:45
  • Please post your models as it's quite hard to understand how they are structured. – frankie567 Oct 17 '19 at 13:48
  • Hi, I just dit it, thanks – Jayanta Oct 17 '19 at 13:49
  • Ok, I see it now. Problem is that one client can have several projects. I see you correctly defined `related_name`. So you could do `client.projects.all()` to have a list of all the projects of a client. But how do you know which one is the "default" in your logic? – frankie567 Oct 17 '19 at 13:55
  • well what do you mean by default ? do you mean the current project that the user is inside ? can you give me an example of how to and where I should client.projects.all() if you dont mind. I am actually new to Django. I am trying to do it, but gives me error – Jayanta Oct 17 '19 at 14:05
  • Well I don't know, that's your question :D Which project do you want to retrieve when you are in `MaterialTagExcel`? – frankie567 Oct 17 '19 at 14:07
  • Hi frankie, I understood now. I want the project_id of the project that the user is currently working on. The logic is like, from a dropdown a user can switch to another project. So in every project mask there is MaterialTagExcel – Jayanta Oct 17 '19 at 14:13

1 Answers1

0

You wish to retrieve the current project the user is working on. The goal of a REST API is to be stateless, which roughly means that the request contains all the necessary information to perform its action without relying on an external context.

This means that you have to provide the current project id in each of your request.

So, in your example, when you want to POST a new MaterialTagExcel, you'll have to provide the Project. You can modify your serializer like this to do so:

class MaterialTagExcelSerializer(BaseSerializer):
    project = serializers.PrimaryKeyRelatedField(write_only=True, queryset=Project.objects.all())

    class Meta:
        fields = "__all__"
        model = MaterialTagExcel

    def create(self, validated_data):

        name = validated_data.get('name')  
        project = validated_data.pop('project') # A Project object

Now, when you're doing a request, you'll have to specify the property project with the id. of the project the user has selected in the menu.

frankie567
  • 1,703
  • 12
  • 20
  • well the idea is to update at the backend without providing any client_id or project_id in the client side. Its like, user enters a name in MaterialTagExcel, this name will be saved in a table MaterialTagExcel and then take the id of this name and project_id and save it to another table called 'MaterialExcelProject' in the backend. I already did the same for client by taking its id and name id and save it to MaterialExcelClient. I have added the serializer for the same. Kindly have a look. – Jayanta Oct 17 '19 at 15:40