User100696
User100696

Reputation: 707

Django - not replacing my string as expected

I need help I have no clue how to solve it.

I'm working with files. Basically I'm opening a file, reading what's inside it, look for a word and replace the word next to it

I'm opening a text file, in this case I have two words which are called with the same name, they are separated for PART 1 and PART 2

this is my car.txt

PART 1

car toyota



PART 2

car toyota

as you can see I have the same word separated for part so my script will look for both and show this in my template..

this is how it's working

views.py

def car_p1():
    file = open("car.txt","r")
    content = file.read()
    file.close()
    car = re.findall('car\s(.*?)\s',open('car.txt','r').read())
    if car:
        print car
    else:
        print 'no car found!'
    return car[0]


def car_p2():
    file = open("car.txt","r")
    content = file.read()
    file.close()
    car = re.findall('car\s(.*?)\s',open('car.txt','r').read())
    if car:
        print car
    else:
        print 'no car found!'
    return car[1]


def get_items(request):
    car = car_p1()
    car2 = car_p2()
    if 'car' in request.POST:
        car_change(request)
        return redirect('get_items')
    return render(request, 'cars.html', {'car':car, 'car2':car2,})

def car_change(request):
    car = car_p1()
    car2 = car_p2()
    if request.method == 'POST':
        change_car = str(request.POST['car_1'])
        change_car_2 = str(request.POST['car_2'])
        filedata= None
        with open('car.txt', 'r') as f:
            filedata = f.read()
            filedata=filedata.replace(car , change_car , 1)
            filedata=filedata.replace(car2 , change_car_2 , 1)
            with open('car.txt', 'wb') as f:
                f.writelines(filedata)
    return render(request, 'cars.html')

Here's my problem. I want to change part 1 from toyota to hyundai and works ok. I get something like this

PART 1

car hyundai

PART 2

car toyota

but if I want to change part 2 from toyota to hyundai won't get replace on part 2, it will replace my part1.. getting something like this:

PART 1

car hyundai

PART 2

car toyota

I want part 2 to make it work as part 1 does... what's wrong with my code?

this is my html:

<form method="post" class="" action="">{% csrf_token %}
    <label for="car1">CAR 1: </label>
    <input id="car1" class="form-control" type="text" name="car_1" value="{{ car }}">
    <br>
    <label for="car2">CAR 2: </label>
    <input id="car2" class="form-control" type="text" name="car_2" value="{{ car2 }}">
    <br>
    <br>
    <input type="submit" name="car" class="btn btn-primary btn-lg btn-block" value="Save">
</form>

hope you could help me.

I'll apreciate your help a lot.

Thanks!!!

Upvotes: 0

Views: 56

Answers (2)

Haifeng Zhang
Haifeng Zhang

Reputation: 31895

As neverwalkaloner mentioned, you always replace the 1st occurrence when you read the whole file into one string filedata. it would be fine if toyota appears only once but would fail when more than once.

You can replace the filedata string from right-to-left for car2.

Change filedata=filedata.replace(car2 , change_car_2 , 1) to filedata=change_car_2.join(filedata.rsplit(car2, 1))

Upvotes: 2

neverwalkaloner
neverwalkaloner

Reputation: 47354

Problem is that replace will replace only first N occurrences in string. If you need to replace second occurrence you can implement custom method, something like this:

def replace_second_car(filedata, old_car, new_car):
     places = [i.start() for i in re.finditer('car\s(.*?)\s',filedata)]
     start_place = places[1]
     return filedata[:start_place] + filedata[start_place:].replace(old_car, new_car)

now in view you can use it like this:

filedata = replace_second_car(filedata, car2, change_car_2)

Upvotes: 2

Related Questions