Search code examples
djangowhitespacepsql

Is there a way to prevent Django from trimming leading white space in a text field?


Is there a way to prevent Django from trimming leading white space in models.TextField? I've been scouring the docs and haven't found anything. The database I'm using is PSQL. Any guidance would be appreciated.

An answer made me aware there is a solution using forms. As of right now, I don't use forms:

class Song(models.Model):
    """
    Fields that are displayed on the Song screeen
    """
    name = models.CharField(max_length=100, blank=True, default="")
    artist = models.CharField(max_length=100, blank=True, default="")
    creator = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
    lyrics = models.TextField(default="", blank=True)
    pulled_lyrics = models.TextField(default="", blank=True)
    chords = models.TextField(default="", blank=True)
    strumming_pattern = models.CharField(max_length=30, default="", blank=True)

    """
    Additional information used to determine where to display the song
    """
    public = models.BooleanField(default=False)
    is_favourite = models.BooleanField(default=False)

    def __str__(self):
        return self.name 
class SongViewSet(viewsets.ModelViewSet):
    serializer_class = SongSerializer

    def get_queryset(self):
        """
        Sets queryset to be songs owned by user
        This makes it so that a user can only manipulate their own songs
        """
        if not self.request.user.is_authenticated:
            return []

        user = self.request.user
        qs = Song.objects.all()
        if user.is_superuser:
            return qs
        else:
            return qs.filter(creator=user)
    
    def create(self, request):
        """
        Create user with given request body
        """
        try:
            song = Song.objects.create(creator=request.user, **request.data)
        except:
            return Response('The provided data was of an invalid form.', status=status.HTTP_400_BAD_REQUEST)
        song_serializer = SongSerializer(song)
        return Response(song_serializer.data, status=status.HTTP_200_OK)

JS (React) code to create a new song and patch a song respectively:

const response = await axios.post(
                "/api/songs/",
                {},
                {
                    withCredentials: true,
                    headers: {
                        "X-CSRFToken": getToken(),
                    },
                }
            );
const songCopy = { ...item }
    delete songCopy["creator"];
    axios.patch(`/api/songs/${item.id}/`, songCopy, {
        withCredentials: true,
        headers: {
            "Content-Type": "application/json",
            "X-CSRFToken": getToken(),
        },
    });

Solution

  • Yes, you form field should set strip=False [Django-doc] in the form, so:

    class MyForm(forms.Form):
        some_field = forms.CharField(strip=False)

    For a serializer this is quite similar, in your serializer you should set trim_whitespace=False [DRF-doc]:

    from rest_framework import serializers
    
    class SongSerializer(ModelSerializer):
        lyrics = serializers.CharField(trim_whitespace=False)

    As the documentation says:

    If True (default), the value will be stripped of leading and trailing whitespace.

    If you render the data then multiple (leading) spaces will be rendered on the webpage as one space. You can make use of <pre> tag as a preformatted text element, so:

    {{ some_variable }}